API reference
Offers
Propose, counter and accept prices on marketplace routes.
7 operationsBase URL https://packetexchange.io/api/v1Postman collection
BrowseOffers
List offers you made and received
GET/
- Access
- API key. Full-access keys only; not reachable by scoped keys.
- Rate limit
- 100 requests per second (the default)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
role | query | string | Default allOne of buyer, seller, all |
status | query | string | -One of pending, countered, accepted, rejected, withdrawn, expired |
Response 200
| Field | Type | Description |
|---|---|---|
datarequired | object[] | - |
idrequireddata[].id | string (uuid) | - |
routeIdrequireddata[].routeId | string (uuid) | - |
groupIdrequireddata[].groupId | string (uuid) | null | Set when the offer is part of a bulk (multi-route) offer |
listPricerequireddata[].listPrice | money | null | The route list price when the offer was made USD as a decimal string with exactly 6 places, e.g. "0.012500". |
proposedPricerequireddata[].proposedPrice | money | The latest price on the table USD as a decimal string with exactly 6 places, e.g. "0.012500". |
agreedPricerequireddata[].agreedPrice | money | null | Set once accepted USD as a decimal string with exactly 6 places, e.g. "0.012500". |
statusrequireddata[].status | string | -One of pending, countered, accepted, rejected, withdrawn, expired |
lastActorrequireddata[].lastActor | string | -One of buyer, seller |
messagerequireddata[].message | string | null | Cleaned of contact details |
expiresAtrequireddata[].expiresAt | string (date-time) | null | ISO-8601 timestamp (UTC) |
createdAtrequireddata[].createdAt | string (date-time) | ISO-8601 timestamp (UTC) |
updatedAtrequireddata[].updatedAt | string (date-time) | ISO-8601 timestamp (UTC) |
rolerequireddata[].role | string | Your side of this offerOne of buyer, seller |
yourTurnrequireddata[].yourTurn | boolean | - |
counterpartyrequireddata[].counterparty | string | Pseudonym for the other side, stable per route |
routerequireddata[].route | object | null | - |
idrequireddata[].route.id | string (uuid) | - |
destinationNamerequireddata[].route.destinationName | string | The seller reads the name they gave the route; the buyer reads the platform-generated name (see MarketplaceRoute.destinationName) |
listingRefdata[].route.listingRef | string | 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. |
countryrequireddata[].route.country | string | - |
countryCoderequireddata[].route.countryCode | string | - |
typerequireddata[].route.type | string | -One of voice, sms |
routeTyperequireddata[].route.routeType | string | - |
pricePerUnitrequireddata[].route.pricePerUnit | money | USD as a decimal string with exactly 6 places, e.g. "0.012500". |
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.
Make an offer on a route
POST/
- Access
- API key. Scoped keys need
offers:write. - Rate limit
- 100 requests per second (the default)
- Safe retries
- Send
X-Idempotency-Key; a replay within 24 hours returns the first response. - Moves money
- Makes or answers a binding offer on a route.
Opens a negotiation at proposedPrice (6-decimal USD string). The seller can accept, reject or counter.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-Idempotency-Key | header | string | Any unique string (a UUID is ideal). Replays within 24 hours return the first response instead of acting twice. |
Request body (application/json)
| Field | Type | Description |
|---|---|---|
routeIdrequired | string (uuid) | - |
proposedPricerequired | string | - |
message | string | -max 500 chars |
Response 200
| Field | Type | Description |
|---|---|---|
datarequired | object | Same fields as Offer, shown earlier on this page. |
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 409
CONFLICT(or a code-specific 409): the change clashes with existing state. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.
Make offers on several routes at once
POST/
- Access
- API key. Scoped keys need
offers:write. - Rate limit
- 100 requests per second (the default)
One offer per item, grouped. Routes that cannot take an offer (your own, inactive, already negotiating) are skipped and reported back.
Request body (application/json)
| Field | Type | Description |
|---|---|---|
itemsrequired | object[] | - |
routeIdrequireditems[].routeId | string (uuid) | - |
proposedPricerequireditems[].proposedPrice | string | - |
message | string | -max 500 chars |
Response 200
| Field | Type | Description |
|---|---|---|
datarequired | object | - |
grouprequireddata.group | object | - |
idrequireddata.group.id | string (uuid) | - |
messagerequireddata.group.message | string | null | - |
statusrequireddata.group.status | string | - |
createdAtrequireddata.group.createdAt | string (date-time) | ISO-8601 timestamp (UTC) |
offersrequireddata.offers | object[] | Same fields as Offer, shown earlier on this page. |
skippedrequireddata.skipped | object[] | - |
routeIdrequireddata.skipped[].routeId | string (uuid) | - |
reasonrequireddata.skipped[].reason | string | - |
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 409
CONFLICT(or a code-specific 409): the change clashes with existing state. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.
List your bulk offers
GET/
- Access
- API key. Full-access keys only; not reachable by scoped keys.
- Rate limit
- 100 requests per second (the default)
Response 200
| Field | Type | Description |
|---|---|---|
datarequired | object[] | - |
idrequireddata[].id | string (uuid) | - |
messagerequireddata[].message | string | null | - |
statusrequireddata[].status | string | - |
createdAtrequireddata[].createdAt | string (date-time) | ISO-8601 timestamp (UTC) |
offersrequireddata[].offers | object[] | Same fields as Offer, shown earlier on this page. |
totalrequireddata[].total | integer | - |
countsrequireddata[].counts | object | Child offers per status |
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.
Accept or reject every open offer in a bulk offer
POST/
- Access
- API key. Scoped keys need
offers:write. - Rate limit
- 100 requests per second (the default)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
idrequired | path | string | - |
Request body (application/json)
| Field | Type | Description |
|---|---|---|
actionrequired | string | -One of accept, reject |
message | string | -max 500 chars |
Response 200
| Field | Type | Description |
|---|---|---|
datarequired | object | - |
groupIdrequireddata.groupId | string (uuid) | - |
appliedrequireddata.applied | integer | - |
resultsrequireddata.results | object[] | - |
okrequireddata.results[].ok | boolean | - |
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 404
NOT_FOUND: no such resource on your account. - 409
CONFLICT(or a code-specific 409): the change clashes with existing state. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.
Get an offer with its negotiation history
GET/
- Access
- API key. Full-access keys only; not reachable by scoped keys.
- Rate limit
- 100 requests per second (the default)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
idrequired | path | string | - |
Response 200
| Field | Type | Description |
|---|---|---|
datarequired | object | - |
idrequireddata.id | string (uuid) | - |
routeIdrequireddata.routeId | string (uuid) | - |
groupIdrequireddata.groupId | string (uuid) | null | Set when the offer is part of a bulk (multi-route) offer |
listPricerequireddata.listPrice | money | null | The route list price when the offer was made USD as a decimal string with exactly 6 places, e.g. "0.012500". |
proposedPricerequireddata.proposedPrice | money | The latest price on the table USD as a decimal string with exactly 6 places, e.g. "0.012500". |
agreedPricerequireddata.agreedPrice | money | null | Set once accepted USD as a decimal string with exactly 6 places, e.g. "0.012500". |
statusrequireddata.status | string | -One of pending, countered, accepted, rejected, withdrawn, expired |
lastActorrequireddata.lastActor | string | -One of buyer, seller |
messagerequireddata.message | string | null | Cleaned of contact details |
expiresAtrequireddata.expiresAt | string (date-time) | null | ISO-8601 timestamp (UTC) |
createdAtrequireddata.createdAt | string (date-time) | ISO-8601 timestamp (UTC) |
updatedAtrequireddata.updatedAt | string (date-time) | ISO-8601 timestamp (UTC) |
rolerequireddata.role | string | Your side of this offerOne of buyer, seller |
yourTurnrequireddata.yourTurn | boolean | - |
counterpartyrequireddata.counterparty | string | Pseudonym for the other side, stable per route |
routerequireddata.route | object | null | - |
idrequireddata.route.id | string (uuid) | - |
destinationNamerequireddata.route.destinationName | string | The seller reads the name they gave the route; the buyer reads the platform-generated name (see MarketplaceRoute.destinationName) |
listingRefdata.route.listingRef | string | 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. |
countryrequireddata.route.country | string | - |
countryCoderequireddata.route.countryCode | string | - |
typerequireddata.route.type | string | -One of voice, sms |
routeTyperequireddata.route.routeType | string | - |
pricePerUnitrequireddata.route.pricePerUnit | money | USD as a decimal string with exactly 6 places, e.g. "0.012500". |
eventsrequireddata.events | object[] | The negotiation timeline, oldest first |
idrequireddata.events[].id | string (uuid) | - |
offerIdrequireddata.events[].offerId | string (uuid) | - |
actorrequireddata.events[].actor | string | - |
actionrequireddata.events[].action | string | - |
pricerequireddata.events[].price | money | null | 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". |
messagerequireddata.events[].message | string | null | - |
createdAtrequireddata.events[].createdAt | string (date-time) | ISO-8601 timestamp (UTC) |
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 404
NOT_FOUND: no such resource on your account. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.
Accept, reject, counter or withdraw an offer
PATCH/
- Access
- API key. Scoped keys need
offers:write. - Rate limit
- 100 requests per second (the default)
- Safe retries
- Send
X-Idempotency-Key; a replay within 24 hours returns the first response. - Moves money
- Makes or answers a binding offer on a route.
price is required for counter. Accepting creates or reprices the purchase at the agreed price.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
idrequired | path | string | - |
X-Idempotency-Key | header | string | Any unique string (a UUID is ideal). Replays within 24 hours return the first response instead of acting twice. |
Request body (application/json)
| Field | Type | Description |
|---|---|---|
actionrequired | string | -One of counter, accept, reject, withdraw |
price | string | - |
message | string | -max 500 chars |
Response 200
| Field | Type | Description |
|---|---|---|
datarequired | object | Same fields as Offer, shown earlier on this page. |
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 404
NOT_FOUND: no such resource on your account. - 409
CONFLICT(or a code-specific 409): the change clashes with existing state. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.