Skip to content

API reference

Purchases

Buy access to marketplace routes and manage what you bought.

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

List your route purchases

GET/api/v1/purchases

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
100 requests per second (the default)

Parameters

  • status

    query · string

    One of active, paused, cancelled
  • cursor

    query · string (uuid)

  • limit

    query · integer

    Default 25

Response 200

  • datarequired

    object[]

  • idrequired

    string (uuid) · data[].id

  • buyerIdrequired

    string (uuid) · data[].buyerId

    Your account id
  • routeIdrequired

    string (uuid) · data[].routeId

  • statusrequired

    string · data[].status

    One of active, paused, cancelled, pending_review
  • sipUsernamerequired

    string | null · data[].sipUsername

  • createdAtrequired

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

    ISO-8601 timestamp (UTC)
  • cancelledAtrequired

    string (date-time) | null · data[].cancelledAt

    ISO-8601 timestamp (UTC)
  • agreedPricerequired

    money | null · data[].agreedPrice

    Negotiated price (from an accepted offer) that overrides the list price USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • heldOldRaterequired

    money | null · data[].heldOldRate

    Set while the purchase is paused by a seller rate increase: the rate you were paying USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • heldNewRaterequired

    money | null · data[].heldNewRate

    The increased rate waiting for your acceptance USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • routingPriorityrequired

    integer | null · data[].routingPriority

    Your routing position (1 = first); null = unranked
  • sipPasswordrequired

    string | null · data[].sipPassword

    Your own SIP password, for your connection card
  • heldDeckVersionrequired

    string | null · data[].heldDeckVersion

    Deck fingerprint to pass as deckVersion when accepting a deck increase
  • routerequired

    object · data[].route

  • typerequired

    string · data[].route.type

    One of voice, sms
  • countryrequired

    string · data[].route.country

  • prefixrequired

    string[] · data[].route.prefix

  • countryCoderequired

    string · data[].route.countryCode

  • destinationNamerequired

    string · data[].route.destinationName

    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.
  • pricePerUnitrequired

    money · data[].route.pricePerUnit

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

    string | null · data[].route.billingIncrement

  • jingleSipIprequired

    enum | null · data[].route.jingleSipIp

    Always null: the seller endpoint is never disclosedOne of null
  • capacityrequired

    integer · data[].route.capacity

  • expectedAsrrequired

    string | null · data[].route.expectedAsr

  • expectedAcdrequired

    string | null · data[].route.expectedAcd

  • dialerCompatiblerequired

    boolean · data[].route.dialerCompatible

  • rateCountrequired

    integer · data[].route.rateCount

  • nextCursorrequired

    string | null

    Pass as cursor to fetch the next page; null on the last page.
  • hasMorerequired

    boolean

    True when another page exists.

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.

Buy access to a marketplace route

POST/api/v1/purchases

Access
API key. Scoped keys need purchases:write.
Rate limit
100 requests per second (the default)
Moves money
Buys access to a marketplace route.

No upfront cost: usage is billed per minute or message from your balance. Requires a LIVE API key: a test key is refused with 400.

Request body (application/json)

  • routeIdrequired

    string (uuid)

Response 201

  • datarequired

    object

  • idrequired

    string (uuid) · data.id

  • buyerIdrequired

    string (uuid) · data.buyerId

    Your account id
  • routeIdrequired

    string (uuid) · data.routeId

  • statusrequired

    string · data.status

    One of active, paused, cancelled, pending_review
  • sipUsernamerequired

    string | null · data.sipUsername

  • createdAtrequired

    string (date-time) · data.createdAt

    ISO-8601 timestamp (UTC)
  • cancelledAtrequired

    string (date-time) | null · data.cancelledAt

    ISO-8601 timestamp (UTC)
  • agreedPricerequired

    money | null · data.agreedPrice

    Negotiated price (from an accepted offer) that overrides the list price USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • heldOldRaterequired

    money | null · data.heldOldRate

    Set while the purchase is paused by a seller rate increase: the rate you were paying USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • heldNewRaterequired

    money | null · data.heldNewRate

    The increased rate waiting for your acceptance USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • routingPriorityrequired

    integer | null · data.routingPriority

    Your routing position (1 = first); null = unranked
  • requiresUsCompliancerequired

    boolean · data.requiresUsCompliance

    A US voice route that needs STIR/SHAKEN review before traffic flows
  • reviewedAtrequired

    string (date-time) | null · data.reviewedAt

    ISO-8601 timestamp (UTC)
  • reviewNoterequired

    string | null · data.reviewNote

    The compliance reviewer's note to you, if any
  • sipPasswordSetrequired

    boolean · data.sipPasswordSet

    Whether a SIP password exists. The value is not returned here: it is shown once at purchase, on your purchased-routes list and on Interconnections.
  • smppSystemIdrequired

    string | null · data.smppSystemId

  • offerIdrequired

    string (uuid) | null · data.offerId

    The accepted offer that set agreedPrice
  • routerequired

    object | null · data.route

  • idrequired

    string (uuid) · data.route.id

  • typerequired

    string · data.route.type

    One of voice, sms
  • countryrequired

    string · data.route.country

  • destinationNamerequired

    string · data.route.destinationName

    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.
  • listingRefrequired

    string · data.route.listingRef

    Anonymous short reference of the listing (4 characters, e.g. "7K2Q"): stable for the life of the listing, unique enough to tell two same-named listings apart, and derived from the listing alone (it says nothing about the seller). Absent on your own listings.
  • pricePerUnitrequired

    money · data.route.pricePerUnit

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

    string | null · data.route.billingIncrement

  • jingleSipIprequired

    enum | null · data.route.jingleSipIp

    One of null
  • sipPublicIprequired

    string · data.sipPublicIp

    Where to send your SIP traffic
  • sipPasswordrequired

    string | null · data.sipPassword

    Plaintext SIP password, returned once here
  • pendingCompliancerequired

    boolean · data.pendingCompliance

    True when US STIR/SHAKEN compliance review must finish before traffic flows

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.

Get your voice routing order

GET/api/v1/purchases/routing-order

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

Your SIP credentials and whitelisted IPs identify your ACCOUNT, not a route, so every active voice purchase can carry any call it covers. When several cover a number equally well (same prefix length), your routing order decides, then the cheaper rate, then the older purchase. This lists every voice purchase that can hold a position (active, paused or pending review): ranked ones first by position, then unranked ones oldest first. Destination names are cleaned of seller details. rateSheet routes are priced by an A-Z deck, so they can overlap any destination.

Response 200

  • datarequired

    object[]

  • purchaseIdrequired

    string (uuid) · data[].purchaseId

  • routeIdrequired

    string (uuid) · data[].routeId

  • statusrequired

    string · data[].status

    One of active, paused, cancelled, pending_review
  • routingPriorityrequired

    integer | null · data[].routingPriority

    Your position (1 = first); null = unranked
  • createdAtrequired

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

    When you bought it (the tie-break among unranked routes)
  • destinationNamerequired

    string · data[].destinationName

    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.
  • countryrequired

    string · data[].country

  • countryCoderequired

    string · data[].countryCode

  • prefixrequired

    string[] · data[].prefix

  • rateSheetrequired

    boolean · data[].rateSheet

    Priced by an A-Z rate sheet, so it can overlap any destination

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.

Replace your voice routing order

PUT/api/v1/purchases/routing-order

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

purchaseIds[0] becomes position 1, the next 2, and so on; every other voice purchase of yours is cleared to unranked. Atomic: a reorder never leaves two routes half-swapped. An empty list clears the whole order (back to cheapest, then oldest). A repeated id is 400 VALIDATION_ERROR; an id that is not one of your rankable voice purchases is 404 and nothing changes.

Request body (application/json)

  • purchaseIdsrequired

    string (uuid)[]

    Your voice purchases in the order to try them; an empty list clears the order

Response 200

  • datarequired

    object

  • orderrequired

    object[] · data.order

  • purchaseIdrequired

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

  • routingPriorityrequired

    integer · data.order[].routingPriority

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.

See your first-choice and backup routes per destination

GET/api/v1/purchases/failover

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

For each prefix your active voice routes list: the route tried first and the backups behind it, in the order a call would use them. When automatic failover is on (enabled: true), a call that a route refuses before it is answered (for example SIP 403, 480, 5xx or no response) is tried straight away on the next route, up to maxAttempts routes, and only the route that connects is billed. A wrong number, a busy or declined call and an unanswered call are never retried. Over a SIP trunk only server errors and congestion (5xx) move a call on; apiOnly marks backups SIP trunk calls never use. singleRoute: true marks a destination with no backup. A-Z rate sheets are listed separately because they have no single prefix. Names are cleaned of seller details. Read-only.

Response 200

  • datarequired

    object

  • enabledrequired

    boolean · data.enabled

    Whether automatic failover is switched on
  • maxAttemptsrequired

    integer · data.maxAttempts

    The most routes tried for one call, the first included
  • destinationsrequired

    object[] · data.destinations

  • prefixrequired

    string · data.destinations[].prefix

    "+" and the listed prefix
  • countryrequired

    string · data.destinations[].country

  • routesrequired

    object[] · data.destinations[].routes

  • purchaseIdrequired

    string (uuid) · data.destinations[].routes[].purchaseId

  • routeIdrequired

    string (uuid) · data.destinations[].routes[].routeId

  • destinationNamerequired

    string · data.destinations[].routes[].destinationName

    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.
  • positionrequired

    integer · data.destinations[].routes[].position

    1 is tried first
  • rolerequired

    string · data.destinations[].routes[].role

    not_tried: beyond maxAttempts, so never reached by one callOne of first, backup, not_tried
  • apiOnlyrequired

    boolean · data.destinations[].routes[].apiOnly

    true for a backup that calls over your SIP trunk never use (it needs SIP credentials, call screening or a reshaped number, or the first choice does); Voice API calls still fail over to it
  • singleRouterequired

    boolean · data.destinations[].singleRoute

    True when only one of your routes covers this prefix: no backup
  • rateSheetsrequired

    object[] · data.rateSheets

  • purchaseIdrequired

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

  • routeIdrequired

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

  • destinationNamerequired

    string · data.rateSheets[].destinationName

    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.

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.

See which of your routes would carry a number

GET/api/v1/purchases/route-for

Access
API key. Scoped keys need routes:read.
Rate limit
60 requests per minute

Runs the same ranking the live SIP path uses, for your account and with the same number normalisation, so the answer is what a real call would do. Lists every route of yours that covers the number, in order, with the step of the rule that put each one behind the one above. Also reports the two refusals that sit in front of routing: an embargoed destination and an empty balance; when refused is set, no route carries the call. Read-only.

Parameters

  • torequired

    query · string

    The number to check, international format

Response 200

  • datarequired

    object

  • numberrequired

    string · data.number

    The number as checked, "+" and digits
  • carriedByrequired

    object | null · data.carriedBy

    The route that would carry it (candidates[0]); null when none covers it
  • positionrequired

    integer · data.carriedBy.position

    1 = the route that would carry the call
  • carriesrequired

    boolean · data.carriedBy.carries

  • purchaseIdrequired

    string (uuid) | null · data.carriedBy.purchaseId

    null for one of your own listings
  • routeIdrequired

    string (uuid) · data.carriedBy.routeId

  • ownRouterequired

    boolean · data.carriedBy.ownRoute

    True when this is a route you sell yourself
  • destinationNamerequired

    string · data.carriedBy.destinationName

    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.
  • countryrequired

    string · data.carriedBy.country

  • matchedPrefixrequired

    string | null · data.carriedBy.matchedPrefix

  • matchedDigitsrequired

    integer · data.carriedBy.matchedDigits

    Length of the matching prefix
  • routingPriorityrequired

    integer | null · data.carriedBy.routingPriority

  • raterequired

    money | null · data.carriedBy.rate

    What you are billed per minute for this number on this route USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • rateSheetrequired

    boolean · data.carriedBy.rateSheet

    The route is priced by an A-Z rate sheet
  • purchasedAtrequired

    string (date-time) | null · data.carriedBy.purchasedAt

    ISO-8601 timestamp (UTC)
  • behindBecauserequired

    string | null · data.carriedBy.behindBecause

    For every route after the first: why the route above it winsOne of prefix, routing_order, rate, age, route_id
  • reasonrequired

    string · data.reason

    Why that route wins, in words
  • decidedByrequired

    string | null · data.decidedBy

    The step that decided between the first two routes; null with fewer than twoOne of prefix, routing_order, rate, age, route_id
  • candidatesrequired

    object[] · data.candidates

    Same fields as RouteForCandidate, shown earlier on this page.
  • refusedrequired

    object | null · data.refused

  • reasonrequired

    string · data.refused.reason

    One of embargoed, no_balance
  • messagerequired

    string · data.refused.message

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.

Set a purchase's routing position

PATCH/api/v1/purchases/{id}/routing-priority

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

Sets (priority: n) or clears (priority: null) one voice purchase's position in your routing order; 1 is tried first. Positions do not have to be contiguous, and two purchases may share one (then rate, then age decides). Voice purchases only, and not a cancelled one (400 VALIDATION_ERROR). To reorder several at once use PUT /purchases/routing-order.

Parameters

  • idrequired

    path · string (uuid)

Request body (application/json)

  • priorityrequired

    integer | null

    1 = tried first; null clears the position1 to 9999

Response 200

  • datarequired

    object

  • idrequired

    string (uuid) · data.id

  • routingPriorityrequired

    integer | null · data.routingPriority

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.
  • 404NOT_FOUND: no such resource on your account.
  • 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.

Clear a purchase's routing position

DELETE/api/v1/purchases/{id}/routing-priority

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

The purchase goes back to unranked: after every ranked route, cheapest then oldest.

Parameters

  • idrequired

    path · string (uuid)

Response 200

  • datarequired

    object

  • idrequired

    string (uuid) · data.id

  • routingPriorityrequired

    integer | null · data.routingPriority

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.
  • 404NOT_FOUND: no such resource on your account.
  • 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.

Get a purchase

GET/api/v1/purchases/{id}

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
100 requests per second (the default)

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

  • idrequired

    string (uuid) · data.id

  • buyerIdrequired

    string (uuid) · data.buyerId

    Your account id
  • routeIdrequired

    string (uuid) · data.routeId

  • statusrequired

    string · data.status

    One of active, paused, cancelled, pending_review
  • sipUsernamerequired

    string | null · data.sipUsername

  • createdAtrequired

    string (date-time) · data.createdAt

    ISO-8601 timestamp (UTC)
  • cancelledAtrequired

    string (date-time) | null · data.cancelledAt

    ISO-8601 timestamp (UTC)
  • agreedPricerequired

    money | null · data.agreedPrice

    Negotiated price (from an accepted offer) that overrides the list price USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • heldOldRaterequired

    money | null · data.heldOldRate

    Set while the purchase is paused by a seller rate increase: the rate you were paying USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • heldNewRaterequired

    money | null · data.heldNewRate

    The increased rate waiting for your acceptance USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • routingPriorityrequired

    integer | null · data.routingPriority

    Your routing position (1 = first); null = unranked
  • requiresUsCompliancerequired

    boolean · data.requiresUsCompliance

    A US voice route that needs STIR/SHAKEN review before traffic flows
  • reviewedAtrequired

    string (date-time) | null · data.reviewedAt

    ISO-8601 timestamp (UTC)
  • reviewNoterequired

    string | null · data.reviewNote

    The compliance reviewer's note to you, if any
  • sipPasswordSetrequired

    boolean · data.sipPasswordSet

    Whether a SIP password exists. The value is not returned here: it is shown once at purchase, on your purchased-routes list and on Interconnections.
  • smppSystemIdrequired

    string | null · data.smppSystemId

  • offerIdrequired

    string (uuid) | null · data.offerId

    The accepted offer that set agreedPrice
  • routerequired

    object | null · data.route

  • idrequired

    string (uuid) · data.route.id

  • typerequired

    string · data.route.type

    One of voice, sms
  • countryrequired

    string · data.route.country

  • destinationNamerequired

    string · data.route.destinationName

    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.
  • listingRefrequired

    string · data.route.listingRef

    Anonymous short reference of the listing (4 characters, e.g. "7K2Q"): stable for the life of the listing, unique enough to tell two same-named listings apart, and derived from the listing alone (it says nothing about the seller). Absent on your own listings.
  • pricePerUnitrequired

    money · data.route.pricePerUnit

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

    string | null · data.route.billingIncrement

  • jingleSipIprequired

    enum | null · data.route.jingleSipIp

    One of null
  • sipPublicIprequired

    string · data.sipPublicIp

    Where to send your SIP traffic

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.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Pause or resume a purchase

PATCH/api/v1/purchases/{id}

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
100 requests per second (the default)

Parameters

  • idrequired

    path · string

Request body (application/json)

  • statusrequired

    string

    One of active, paused

Response 200

  • datarequired

    object

  • idrequired

    string (uuid) · data.id

  • buyerIdrequired

    string (uuid) · data.buyerId

    Your account id
  • routeIdrequired

    string (uuid) · data.routeId

  • statusrequired

    string · data.status

    One of active, paused, cancelled, pending_review
  • sipUsernamerequired

    string | null · data.sipUsername

  • createdAtrequired

    string (date-time) · data.createdAt

    ISO-8601 timestamp (UTC)
  • cancelledAtrequired

    string (date-time) | null · data.cancelledAt

    ISO-8601 timestamp (UTC)
  • agreedPricerequired

    money | null · data.agreedPrice

    Negotiated price (from an accepted offer) that overrides the list price USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • heldOldRaterequired

    money | null · data.heldOldRate

    Set while the purchase is paused by a seller rate increase: the rate you were paying USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • heldNewRaterequired

    money | null · data.heldNewRate

    The increased rate waiting for your acceptance USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • routingPriorityrequired

    integer | null · data.routingPriority

    Your routing position (1 = first); null = unranked
  • requiresUsCompliancerequired

    boolean · data.requiresUsCompliance

    A US voice route that needs STIR/SHAKEN review before traffic flows
  • reviewedAtrequired

    string (date-time) | null · data.reviewedAt

    ISO-8601 timestamp (UTC)
  • reviewNoterequired

    string | null · data.reviewNote

    The compliance reviewer's note to you, if any
  • sipPasswordSetrequired

    boolean · data.sipPasswordSet

    Whether a SIP password exists. The value is not returned here: it is shown once at purchase, on your purchased-routes list and on Interconnections.
  • smppSystemIdrequired

    string | null · data.smppSystemId

  • offerIdrequired

    string (uuid) | null · data.offerId

    The accepted offer that set agreedPrice

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.
  • 404NOT_FOUND: no such resource on your account.
  • 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.

Cancel a purchase

DELETE/api/v1/purchases/{id}

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
100 requests per second (the default)

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

    Same fields as PurchaseRow, shown earlier on this page.

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.
  • 404NOT_FOUND: no such resource on your account.
  • 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.

Get call counts, ASR and spend for a purchase

GET/api/v1/purchases/{id}/usage

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
100 requests per second (the default)

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

  • calls24hrequired

    integer · data.calls24h

  • calls7drequired

    integer · data.calls7d

  • calls30drequired

    integer · data.calls30d

  • totalCallsrequired

    integer · data.totalCalls

  • lastActivityAtrequired

    string (date-time) | null · data.lastActivityAt

    ISO-8601 timestamp (UTC)
  • spend30d

    money · data.spend30d

    Absent when nothing was spent USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • measuredAsr

    number · data.measuredAsr

  • measuredAsrSessions

    integer · data.measuredAsrSessions

  • measuredAsrPopulation

    string · data.measuredAsrPopulation

  • measuredAsrWindow

    string · data.measuredAsrWindow

  • measuredAcd

    number · data.measuredAcd

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.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Accept a seller's rate increase

POST/api/v1/purchases/{id}/accept-rate

Access
API key. Scoped keys need purchases:write.
Rate limit
100 requests per second (the default)
Moves money
Accepts a higher rate on a route you buy.

A purchase paused by a price rise resumes at the new rate. Pass the rate (or deck version) you reviewed so a further change is not accepted by mistake.

Parameters

  • idrequired

    path · string

Request body (application/json)

  • acceptedRate

    string | number

    The new rate you are agreeing to, as shown to you (guards against a further change in between)
  • deckVersion

    string

    For A-Z decks: the heldDeckVersion you reviewed
  • changeId

    string (uuid)

    Accept a SCHEDULED change in advance (id from upcoming-rate-changes). Nothing resumes or bills now.

Response 200

  • datarequired

    object

  • id

    string (uuid) · data.id

  • buyerId

    string (uuid) · data.buyerId

    Your account id
  • routeId

    string (uuid) · data.routeId

  • status

    string · data.status

    One of active, paused, cancelled, pending_review
  • sipUsername

    string | null · data.sipUsername

  • createdAt

    string (date-time) · data.createdAt

    ISO-8601 timestamp (UTC)
  • cancelledAt

    string (date-time) | null · data.cancelledAt

    ISO-8601 timestamp (UTC)
  • agreedPrice

    money | null · data.agreedPrice

    Negotiated price (from an accepted offer) that overrides the list price USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • heldOldRate

    money | null · data.heldOldRate

    Set while the purchase is paused by a seller rate increase: the rate you were paying USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • heldNewRate

    money | null · data.heldNewRate

    The increased rate waiting for your acceptance USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • routingPriority

    integer | null · data.routingPriority

    Your routing position (1 = first); null = unranked
  • requiresUsCompliance

    boolean · data.requiresUsCompliance

    A US voice route that needs STIR/SHAKEN review before traffic flows
  • reviewedAt

    string (date-time) | null · data.reviewedAt

    ISO-8601 timestamp (UTC)
  • reviewNote

    string | null · data.reviewNote

    The compliance reviewer's note to you, if any
  • sipPasswordSet

    boolean · data.sipPasswordSet

    Whether a SIP password exists. The value is not returned here: it is shown once at purchase, on your purchased-routes list and on Interconnections.
  • smppSystemId

    string | null · data.smppSystemId

  • offerId

    string (uuid) | null · data.offerId

    The accepted offer that set agreedPrice
  • accepted

    boolean · data.accepted

    One of true
  • changeId

    string (uuid) · data.changeId

  • purchaseId

    string (uuid) · data.purchaseId

  • effectiveDate

    string (date-time) · data.effectiveDate

    ISO-8601 timestamp (UTC)

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.
  • 404NOT_FOUND: no such resource on your account.
  • 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.

List scheduled rate changes on a route you bought

GET/api/v1/purchases/{id}/upcoming-rate-changes

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

Rate changes the seller has scheduled on a route you bought and that are not yet in effect, soonest first: the effective date, the old and new rate per destination (biggest increases first, at most 200 rows per change; totalRows is the full count), and whether you have already accepted each one. For a per-country listing of an A-Z deck, only that listing's destinations are shown. Accept a change in advance with POST /purchases/{id}/accept-rate and changeId: at the effective date an accepted purchase keeps running instead of being paused for re-consent. affectsYou is false when you do not pay the list rate (an accepted offer or a private price), so a change will not pause you. Destination names are cleaned of seller details.

Parameters

  • idrequired

    path · string (uuid)

Response 200

  • datarequired

    object

  • purchaseIdrequired

    string (uuid) · data.purchaseId

  • affectsYourequired

    boolean · data.affectsYou

    True when you pay the list rate, so this change would pause you until accepted
  • changesrequired

    object[] · data.changes

  • changeIdrequired

    string (uuid) · data.changes[].changeId

    Pass as changeId to POST /purchases/{id}/accept-rate
  • kindrequired

    string · data.changes[].kind

    flat = the route's single price changes; deck = rate-sheet rows changeOne of flat, deck
  • effectiveDaterequired

    string (date-time) · data.changes[].effectiveDate

    ISO-8601 timestamp (UTC)
  • increasesrequired

    integer · data.changes[].increases

  • decreasesrequired

    integer · data.changes[].decreases

  • addedrequired

    integer · data.changes[].added

  • removedrequired

    integer · data.changes[].removed

  • largestIncreasePctrequired

    number | null · data.changes[].largestIncreasePct

  • acceptedrequired

    boolean · data.changes[].accepted

  • acceptedAtrequired

    string (date-time) | null · data.changes[].acceptedAt

    ISO-8601 timestamp (UTC)
  • rowsrequired

    object[] · data.changes[].rows

  • destinationrequired

    string | null · data.changes[].rows[].destination

  • prefixrequired

    string | null · data.changes[].rows[].prefix

  • oldRaterequired

    money | null · data.changes[].rows[].oldRate

    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".
  • newRaterequired

    money | null · data.changes[].rows[].newRate

    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".
  • oldIncrementrequired

    string | null · data.changes[].rows[].oldIncrement

  • newIncrementrequired

    string | null · data.changes[].rows[].newIncrement

  • deltaPctrequired

    number | null · data.changes[].rows[].deltaPct

  • removedrequired

    boolean · data.changes[].rows[].removed

  • totalRowsrequired

    integer · data.changes[].totalRows

    Rows in the change for this listing (rows is capped at 200)

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.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.