← pstn2.org

Live test endpoint · protocol v1.1

PSTN2 Test CP

A dummy Communication Provider you can point your implementation at. It answers the Number Discovery question, “who has this number?”, for a handful of test numbers. One of them has been ported, so you can test the redirect.

How it is set up

Test numbering list

Stands in for Ofcom's S1–S9 lists plus the PSTN2 Range Holder URL field.

numbering-list.json · .csv

Test CP A

The Range Holder for 07700 900 0xx. It has ported 07700 900003 out to Test CP B.

https://pstn2.org/testcp/a · keys

Test CP B

The Range Holder for 07700 900 1xx. It holds 07700 900003, which was ported in from A.

https://pstn2.org/testcp/b · keys

All numbers come from Ofcom's reserved drama range 07700 900xxx, so they never belong to real subscribers. This is a test list, not Ofcom data. The host is static, so only Number Discovery is available here. Authentication and routing are exercised against the local mock network in the test harness download.

Test numbers

E.164NationalExpected result
+44770090000107700 900001held by Test CP A (unported)
+44770090000207700 900002held by Test CP A (unported)
+44770090000307700 900003Test CP A redirects -> held by Test CP B (ported)
+44770090000407700 900004held by Test CP A; querying Test CP B directly returns not_held + invalidate (stale-cache test)
+44770090010107700 900101held by Test CP B (unported)
+44770090009907700 900099404 from Test CP A (not in service)

Try it

Query the Range Holder for a ported number. You get a redirect to Test CP B:

curl -A "pstn2-curl/1.1" https://pstn2.org/testcp/a/pstn2/v1/numbers/447700900003

Follow it:

curl -A "pstn2-curl/1.1" https://pstn2.org/testcp/b/pstn2/v1/numbers/447700900003

Always send a descriptive User-Agent. The host's firewall rejects the default curl/* and Go-http-client/* agents. The SDKs send pstn2-<language>-sdk/1.1.0.

With the SDKs

# TypeScript
cd code/typescript && npm install && PSTN2_NETWORK=live npm run example:05

# Python
cd code/python && pip install -e . && PSTN2_NETWORK=live python examples/05_number_discovery.py

# Go
cd code/go && PSTN2_NETWORK=live go run ./examples/05-number-discovery

The algorithm you are testing

  1. Cache: if you hold an unexpired answer for the number, query that CP directly.
  2. Numbering list: find the block by longest prefix. That gives you the Range Holder and its URL.
  3. Range Holder: GET {url}/pstn2/v1/numbers/{digits}. The answer is held, or a redirect to the CP the number was ported to.
  4. Retry at the CP named in the redirect. Stop after 5 hops, and stop if you reach the same CP twice.
  5. Cache the answer for cache.ttl seconds. If any later response says not_held with cache.invalidate, purge the entry and start again from step 2.

Signatures: every answer is signed with Ed25519 over the canonical JSON of the body without the signature field (keys sorted, no whitespace). Verify it with the key named by kid at {url}/pstn2/v1/keys. Full details are in the specification, §9 Number Discovery.