Skip to content

API reference

Onboarding

The guided first-call flow for new accounts.

4 operationsBase URL https://packetexchange.io/api/v1Postman collection

Get everything the first-call guide needs

GET/api/v1/first-call/state

Access
API key. Scoped keys need account:read.
Rate limit
100 requests per second (the default)

Balance, verification, active purchases (with where to send traffic and the billing increment), the five most recent calls and the account connectivity brief. If the brief cannot be read, brief is null and briefError says why; no fallback address is ever guessed.

Response 200

  • datarequired

    object

  • balancerequired

    money · data.balance

    USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • balanceNumericrequired

    number · data.balanceNumeric

  • emailVerifiedrequired

    boolean · data.emailVerified

  • accountStatusrequired

    string | null · data.accountStatus

  • activePurchasesrequired

    object[] · data.activePurchases

  • purchaseIdrequired

    string (uuid) · data.activePurchases[].purchaseId

  • routeIdrequired

    string (uuid) · data.activePurchases[].routeId

  • routeNamerequired

    string | null · data.activePurchases[].routeName

    The listing name as a buyer reads it: generated by the platform, never the seller's text, and ending in the listing reference (e.g. "Niger Mobile · Ref 7K2Q", "A-Z Voice · Premium · Full CLI · Ref 3MX9"). Your own listings keep the name you gave them.
  • countryCoderequired

    string | null · data.activePurchases[].countryCode

  • prefixesrequired

    string | null · data.activePurchases[].prefixes

    Comma-joined prefixes
  • typerequired

    string · data.activePurchases[].type

  • statusrequired

    string · data.activePurchases[].status

  • billingIncrementrequired

    string | null · data.activePurchases[].billingIncrement

    e.g. "60/60"
  • sipUsernamerequired

    string | null · data.activePurchases[].sipUsername

  • hasSipPasswordrequired

    boolean · data.activePurchases[].hasSipPassword

  • sendTorequired

    string | null · data.activePurchases[].sendTo

    Our address to send this traffic to, from the live brief
  • sendToPortrequired

    integer | null · data.activePurchases[].sendToPort

  • recentCallsrequired

    object[] · data.recentCalls

  • idrequired

    string (uuid) · data.recentCalls[].id

  • createdAtrequired

    string (date-time) · data.recentCalls[].createdAt

    ISO-8601 timestamp (UTC)
  • directionrequired

    string · data.recentCalls[].direction

  • kindrequired

    string · data.recentCalls[].kind

  • toNumberrequired

    string | null · data.recentCalls[].toNumber

  • fromNumberrequired

    string | null · data.recentCalls[].fromNumber

  • statusrequired

    string | null · data.recentCalls[].status

  • sipCoderequired

    integer | null · data.recentCalls[].sipCode

  • hangupCauserequired

    string | null · data.recentCalls[].hangupCause

  • durationSecondsrequired

    integer | null · data.recentCalls[].durationSeconds

  • billedSecondsrequired

    integer | null · data.recentCalls[].billedSeconds

    Seconds the charge was computed from, after increment rounding
  • buyerCostrequired

    money | null · data.recentCalls[].buyerCost

    US dollars as a decimal string with exactly 6 decimal places, e.g. "0.012500". Do money arithmetic with a decimal type, not floating point. USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • ratePerUnitrequired

    money | null · data.recentCalls[].ratePerUnit

    US dollars as a decimal string with exactly 6 decimal places, e.g. "0.012500". Do money arithmetic with a decimal type, not floating point. USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • isTestrequired

    boolean · data.recentCalls[].isTest

  • hasAnyCallrequired

    boolean · data.hasAnyCall

  • briefrequired

    object | null · data.brief

    The account connectivity brief: authorised source addresses, purchased routes and where to send them
  • briefErrorrequired

    string | null · data.briefError

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Check first-call progress

GET/api/v1/first-call/status

Access
API key. Scoped keys need account:read.
Rate limit
100 requests per second (the default)

Three cheap yes/no checks for a progress badge: any call made, any active purchase, a positive balance.

Response 200

  • datarequired

    object

  • hasAnyCallrequired

    boolean · data.hasAnyCall

  • hasActivePurchaserequired

    boolean · data.hasActivePurchase

  • hasBalancerequired

    boolean · data.hasBalance

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Activate your own switch address

POST/api/v1/first-call/switch-address

Access
API key. Scoped keys need account:write.
Rate limit
10 requests per minute

Moves the account onto its own ingress address. Call without confirm to preview what changes; send confirm: true to apply.

Request body (application/json)

  • confirm

    boolean

Response 200

  • datarequired

    object

    What was (or would be) changed

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Check whether a call to a destination would be accepted

POST/api/v1/first-call/readiness

Access
API key. Scoped keys need account:read.
Rate limit
20 requests per minute

Dry-runs inbound admission for a destination against each way your traffic can be recognised (source address or SIP credentials). Places no call and moves no money. When refused, rejection explains why and whose move it is.

Request body (application/json)

  • destinationrequired

    string

    Destination number in international formatmax 24 chars

Response 200

  • datarequired

    object

  • checkablerequired

    boolean · data.checkable

  • acceptedrequired

    boolean · data.accepted

  • identityCheckedrequired

    string | null · data.identityChecked

  • identitiesTriedrequired

    string[] · data.identitiesTried

  • rejectionrequired

    object | null · data.rejection

  • coderequired

    integer · data.rejection.code

    Stable PacketExchange cause code (not the SIP code)
  • blockedByrequired

    string · data.rejection.blockedBy

    Whose move it is to unblock the call
  • reasonrequired

    string · data.rejection.reason

  • remedyrequired

    string · data.rejection.remedy

  • sipCoderequired

    integer · data.rejection.sipCode

  • noterequired

    string | null · data.note

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.