Skip to main content

Number Lookup API (BETA) (1.0.0)

Download OpenAPI specification:Download

Spirius Support: support@spirius.com License: Proprietary

Number Lookup API Description

Answers questions about a phone number: which network serves it, whether it was ported and from whom, every port on record, and whether it is reachable right now. One canonical response shape for every country; the data behind it differs per country, and the response says what kind of data answered and how fresh it is.

Base URL

Every path is relative to https://api.spirius.com/numberlookup.

Authentication

HTTP Basic. Send the account username and password on every request as Authorization: Basic <base64(username:password)>. The username is matched without regard to case; the password is matched exactly. Any other scheme is refused. Always call the API over HTTPS.

Each view needs a scope granted to the account:

Scope Grants
numbers:read GET /v1/numbers/{number}
numbers:porting-history the porting-history view, together with numbers:read
numbers:live-status the live-status view, together with numbers:read

Missing or wrong credentials answer 401 with a Basic challenge. Access is checked on every request, and a refusal that other credentials would not fix answers 403: a calling address the client's IP lists do not allow, a client that may not use the API, or a view whose scope is not granted. Contact Spirius support to enable the API or add a scope.

Number format

The number in the path is E.164: digits with a leading +, the digits alone, or a 00 international prefix. Spaces and dashes are ignored. A number in national format, of the wrong length, or with an unassigned country code is not an error: the answer is HTTP 200 with the finding invalid_number. The canonical digits (no +) are returned in number.e164 and in the Content-Location header, the canonical path of the view. On invalid_number the number was not parsed: number.e164 carries the input as received and no Content-Location is set.

Views

View Path Returns HTTP caching
Base GET /v1/numbers/{number} number, network, portability, findings, source until source.valid_until; no-store when it is null
Porting history GET /v1/numbers/{number}/porting-history base + porting_history until the earlier valid_until; no-store when either is null
Live status GET /v1/numbers/{number}/live-status base + live_status until the earlier valid_until; no-store when either is null

What a client may cache follows from the answer's content, not from the view alone: see Freshness and caching.

An optional field the data has nothing for is absent, never null. The one exception is source.valid_until, which is null when there is no such time: a number_range answer, or a live status that is not reused (unavailable).

Findings

Findings are answers, not errors, and come with HTTP 200:

Finding Meaning
invalid_number The input is not a well-formed E.164 number. Nothing else is looked up.
unallocated_range The number lies in no allocated range.
unsupported_country No data is available for the country, or the number is a global service number.
not_mobile The number is a landline or a service number; number.type says which.

Freshness and caching

source.basis says what kind of data answered, and valid_until says how long it stays current:

Data source.basis valid_until
National portability registry, authoritative for the serving provider portability_registry The next registry snapshot, daily
Live status reachable, absent live_network Minutes
Live status barred live_network Hours
Live status unknown_subscriber, not_provisioned live_network About a day
Live status unavailable live_network null, never reused
Number range only, serving provider unknown number_range null

A live status is reused until its valid_until instead of querying the network again. as_of and checked_at keep the time the data was obtained, so a reused answer shows its age.

Every view answer carries these headers:

Header Value When
ETag Strong validator of the exact body Always. Send it in If-None-Match to get 304 Not Modified.
Cache-Control private, max-age=N Until the earliest valid_until of the answer's parts.
Cache-Control private, no-cache The earliest valid_until has passed, for example when a registry snapshot is late.
Cache-Control private, no-store A part has valid_until: null, or the answer is a finding only.
Vary Authorization Always.

Partial answers

When the base answer resolves but the requested aspect cannot be obtained, the view still answers 200 with the aspect present and marked: live_status.state is unavailable, or porting_history carries its source and no ports. Only a failure of the base answer itself is an error.

Errors

Errors are answered as application/problem+json (RFC 9457) with type, title, status, detail and instance.

Status type When
401 https://developer.spirius.com/problems/unauthorized Missing or wrong credentials.
403 https://developer.spirius.com/problems/forbidden The calling address is not allowed, the client may not use the API, or the scope of the view is not granted.
429 https://developer.spirius.com/problems/rate-limited The client's request rate is exceeded; Retry-After gives the pause in seconds.
429 https://developer.spirius.com/problems/quota-exceeded The client's monthly lookup quota is exhausted; Retry-After is when it resets.
503 https://developer.spirius.com/problems/provider-unavailable No data source could answer for the country right now; Retry-After in seconds.
503 https://developer.spirius.com/problems/service-unavailable The lookup could not be completed right now; Retry-After in seconds.
404 https://developer.spirius.com/problems/not-found No resource exists at the path.
405 https://developer.spirius.com/problems/method-not-allowed The method is not allowed on the path. Every view is GET.
500 https://developer.spirius.com/problems/internal-error An unexpected error. The detail asks you to contact support with the request path and time.

Rate limits and quotas

Every account has a request rate: up to a burst of requests at once, then a sustained number of lookups per second. It may also have a monthly lookup quota. Both are agreed per account. Exceeding either answers 429 with Retry-After. A lookup that fails on the service side is never counted.

Numbers

Views of one number (network and portability, porting history, live status).

Base view: network and portability of one number

The base view: serving network, portability state, findings and the freshness of the data behind them. Any input that is not a well-formed E.164 number answers 200 with the finding invalid_number; number.e164 then carries the input as received and no Content-Location is set. Needs the numbers:read scope.

Authorizations:
basicAuth
path Parameters
number
required
string
Example: +46701234567

The number, E.164 with or without the leading plus, or with a 00 prefix. Spaces and dashes are ignored.

header Parameters
If-None-Match
string

An ETag from an earlier answer. A match answers 304.

Responses

Response samples

Content type
application/json
{
  • "number": {
    },
  • "network": {
    },
  • "portability": {
    },
  • "findings": [ ],
  • "source": {
    }
}

Base view plus every retained port of one number

The base view plus porting_history: every port on record newest first where the registry retains the history, otherwise the latest port alone. When the base resolves but the history cannot be obtained, the aspect is present with its source and no ports. On invalid_number, number.e164 carries the input as received. Needs numbers:read and numbers:porting-history.

Authorizations:
basicAuth
path Parameters
number
required
string
Example: +46701234567

The number, E.164 with or without the leading plus, or with a 00 prefix. Spaces and dashes are ignored.

header Parameters
If-None-Match
string

An ETag from an earlier answer. A match answers 304.

Responses

Response samples

Content type
application/json
{
  • "number": {
    },
  • "network": {
    },
  • "portability": {
    },
  • "findings": [ ],
  • "source": {
    },
  • "porting_history": {
    }
}

Base view plus the live network status of one number

The base view plus live_status, a live query of the mobile network, or a recent one reused for a time that depends on the state (see Freshness and caching; checked_at is when the network answered, and Cache-Control gives the exact remaining validity). When no live answer can be obtained, the aspect is present with state: unavailable and the base answer stands. On invalid_number, number.e164 carries the input as received. A live answer is cacheable until its valid_until. Needs numbers:read and numbers:live-status.

Authorizations:
basicAuth
path Parameters
number
required
string
Example: +46701234567

The number, E.164 with or without the leading plus, or with a 00 prefix. Spaces and dashes are ignored.

header Parameters
If-None-Match
string

An ETag from an earlier answer. A match answers 304.

Responses

Response samples

Content type
application/json
{
  • "number": {
    },
  • "network": {
    },
  • "portability": {
    },
  • "findings": [ ],
  • "source": {
    },
  • "live_status": {
    }
}