DocsAPI

Limits, retries & errors

How many calls you may make, how to retry without paying twice, and what every error answer means.

This page covers the rules every call shares: rate limits, safe retries, paging and errors. The base address is https://api.vortexdeployer.com/api/v1.

Rate limits#

A rate limit caps how many calls you make per minute. Only reads count. Checking a marketplace order counts as a read too.

CallsPer keyPer account
GET and HEAD, and an order check300 a minute600 a minute
Every other POST, PATCH, DELETEno limitno limit

An order check is POST /marketplace/orders/:id/check. It moves no funds and only reads where your order stands, so it counts like a GET. See Wallet marketplace.

All the keys on one account share the account's 600. Buys, sells, batches and launches have no per-minute limit. Neither does making a marketplace order. A key's caps and wallet list guard spending instead. See API overview & keys.

Each read answer, an order check too, has three headers about the key's minute:

HeaderMeaning
X-RateLimit-LimitReads a minute the key allows.
X-RateLimit-RemainingReads left this minute.
X-RateLimit-ResetWhen the count starts again, in Unix seconds.

Over the limit, you get 429 and a Retry-After header in seconds. The body has the same number:

{ "code": "rate_limited", "error": "rate limit reached — slow down", "retryAfterSeconds": 12, "traceId": "…" }

Wait that many seconds, then go on.

Bad keys count too. After 30 calls with a wrong or revoked key from one IP address in a minute, every call from it gets 429 auth_rate_limited for a minute.

Retry safely#

A network can drop the answer after the work is done. If you just send the call again, you may buy twice.

An idempotency key stops that. It is a name you pick for one operation, sent in the Idempotency-Key header. Send the same name again and the API answers from its record. It does not run the work twice.

curl -s -X POST https://api.vortexdeployer.com/api/v1/buy \
  -H "Authorization: Bearer vd_…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: buy-7xKX-2026-10-18-0001" \
  -d '{ "mint": "7xKX…pump", "walletId": "812", "amountSol": 0.05 }'
  • Use one on every POST, PATCH and DELETE that moves money: buys, sells, batches, launches, claims and tasks.
  • A Wallet Marketplace order uses its own requestKey instead. See Request key: safe retries.
  • It is 8 to 128 characters: letters, digits, -, _ and :. Anything else gets 400 invalid_idempotency_key.
  • Make it unique per operation. A new trade needs a new key.
  • Keys belong to your account. Two of your API keys share them.
  • The answer echoes the key in the x-idempotency-key header.
A retry without the header is a new trade

Without Idempotency-Key, sending a buy again buys again.

What a repeat returns#

You sendYou get
The same key and the same body, after the first call endedThe first call's status and body. Nothing runs again.
The same key and body while the first call still runsThe API waits about 5 seconds. Then it answers, or gives 409 operation_pending.
The same key with a different body409 idempotency_conflict.

A repeated answer has an x-operation-state header:

  • complete — the operation is over. Its confirmed and err fields show the chain's latest word.
  • pending — a transaction is still on its way. Ask again later with the same key.

operation_pending carries "operationId" (your key) and "pending": true. The first call's transaction is never sent twice. Wait a few seconds and ask again with the same key.

Same key or new key?#

  • You got no answer (a timeout or a dropped line): send again with the same key and body.
  • You got an answer, even an error: that answer is saved under the key. To try again with a fixed body, use a new key.

A long call can be cut off after about 100 seconds before its answer reaches you. The work goes on. Ask again with the same key to get the result.

Paging#

Long lists are paged with ?limit= and ?offset=.

  • limit is 1 to 500. Default 200.
  • offset starts at 0.
  • X-Total-Count holds the full size of the list.
  • A limit out of range gets 400 validation_failed.

A few lists page in their own way, like GET /events and GET /marketplace/inventory. Their pages say so.

Errors#

Every error is JSON with the same fields:

{ "code": "insufficient_scope", "error": "this API key does not have the 'trade' scope", "traceId": "9f1c…" }
  • code — a fixed name for the problem. Your code should check this.
  • error — words for people. The wording can change.
  • traceId — a trace id for this one call. Give it to support when you ask for help.

A bad body or query gets validation_failed, and details lists each problem:

{
  "code": "validation_failed",
  "error": "validation failed",
  "details": [ { "path": "amountSol", "message": "Too small: expected number to be >0" } ],
  "traceId": "…"
}

Some codes add a field that names the limit:

  • over_trade_cap adds maxSolPerTrade.
  • over_daily_cap adds dailySolCap.
  • wallet_not_allowed adds walletId.
  • rate_limited and auth_rate_limited add retryAfterSeconds.

A route that does not exist gets 404 not_found with "no such API route".

Codes#

CodeStatusWhat it means and what to do
validation_failed400The body or query is wrong. Fix what details names.
invalid_idempotency_key400The Idempotency-Key header is malformed.
bad_request400The API understood the call but will not do it. error says why.
invalid_api_key401The key is missing, wrong or revoked. Stop and tell the key's owner.
unauthorized401A 401 with no other code. Treat it like invalid_api_key.
insufficient_scope403The key lacks the scope this route needs.
ip_not_allowed403The call came from an IP address the key does not allow.
key_restricted403A key with limits tried something only a key with no limits may do.
sandbox_key403A sandbox key sent a real call. Add "dryRun": true.
wallet_not_allowed403The wallet is not on the key's wallet list.
private_key_not_allowed403A key with a wallet list sent a private key.
over_trade_cap403A buy is over the key's max per buy.
over_daily_cap403The buy would pass the key's daily cap.
forbidden403The thing you named is not yours, or you may not do this.
not_found404No such route, or no such item in your account.
idempotency_conflict409You used this Idempotency-Key for a different body.
operation_pending409The first call with this key still runs. Ask again with the same key.
conflict409The call does not fit the current state, like pausing a stopped task.
payload_too_large413The body is too big. Most routes take up to 256 KB, POST /launch 15 MB and task calls 10 MB.
unprocessable422It cannot be done, like selling a token the wallet does not hold.
rate_limited429Too many reads. Wait Retry-After seconds.
auth_rate_limited429Too many bad keys from your IP address. Wait a minute.
internal_error500Something broke on our side. Note the traceId.
service_unavailable503Out of service for a moment. Wait, then ask again.

A route may also send a code that is not listed here. Then go by the status.

A 503 with operation_pending means the work ran but its answer was not saved. Ask again later with the same key. Do not send it as new.

Each route's statuses and codes are in the OpenAPI document at https://api.vortexdeployer.com/api/v1/openapi.json.

Ask for a feature#

Missing an endpoint, field or stream? In the app, open API and then the Feature requests tab. Fill in Request title and Request details, then click Send request. Your requests and their status show in the same tab.

See also#