Skip to content

Idempotency, errors and limits

If a request times out, you do not know whether it succeeded. Retry the same operation with the same Idempotency-Key to avoid creating a second payment.

  1. Generate a unique key before the first request and save it with your order.
  2. Send it in Idempotency-Key when creating or changing a business resource.
  3. After a timeout, retry the same method, path and body with that key.
  4. For a new action, create a new key.

The key must be non-empty and no longer than 128 bytes. Repeating a completed action returns its stored response. Changing the body under the same key returns 409 idempotency_conflict.

This applies to business mutations such as invoices, shops, keys and webhooks. Read-only GET calls and sign-in challenges do not use this mechanism. Follow each endpoint’s requirements.

external_id helps associate a payment with your order; it is not an idempotency key.

Example:

{"error":{"code":"idempotency_conflict","message":"idempotency_conflict"}}

Use error.code in your program. Do not infer success from the response body without first checking the HTTP status.

Code Next action
unauthorized Check the credential, permissions and any IP restriction. Sign in again if the session expired.
mfa_required Complete the account’s second factor using its session.
onboarding_required Complete /onboarding before shop operations.
idempotency_key_required Supply a saved non-empty key, at most 128 bytes.
idempotency_conflict Find the original request. Do not silently create a new payment.
json_content_type_required / invalid_json Send Content-Type: application/json and only documented fields.
unsupported_network / unsupported_asset Select a supported network and token.
network_not_ready / asset_not_ready Wait for availability or select another ready route.
amount_below_minimum / fee_exceeds_amount Check the amount, decimals and shop terms.
shop_archived / shop_not_found Check the shop and access.
invalid_expires_in Send 1d, 7d, 30d, 180d or 365d, and only when creating an invoice. Deposits do not expire.
invalid_assets / issuance_in_group Send distinct {chain_id, token} pairs without chain_id and token; cancel or pause a group by its own id. See several tokens or networks.
solana_setup_required / tron_setup_required Set the shop’s Solana or Tron recipient first.
invoice_amount_limit / sandbox_amount_limit Lower the amount to within the limit.
active_invoice_limit_reached / deposit_address_limit_reached Cancel invoices or disable deposits you no longer need, or ask Invoise to raise the limit.
api_key_limit_reached / too_many_allowed_ips / webhook_limit_reached Revoke unused keys, shorten the IP list or reuse an existing endpoint.
team_limit_reached Remove a member or revoke a pending invitation, or ask Invoise to raise the limit.
account_disabled Invoise staff blocked the account; the reason is in error.details. See blocked accounts.
rate_limited Wait for the number of seconds in Retry-After before retrying.

When a request would exceed a limit, Invoise rejects it with the usual error body and the code below.

Limit Value Error
Amount of one invoice 1,000,000 tokens 400 invoice_amount_limit
Amount of one sandbox invoice or simulated transfer 10,000 tokens 400 sandbox_amount_limit
Active invoices per merchant 2,000 400 active_invoice_limit_reached
Active deposit addresses per merchant, per network family EVM 10,000, Tron 10,000, Solana 10 400 deposit_address_limit_reached
API keys per shop that are not revoked 10 400 api_key_limit_reached
Allowed IP addresses or CIDR ranges per key 10 400 too_many_allowed_ips
Webhook endpoints per shop 10 400 webhook_limit_reached
Team members and pending invitations per merchant 10 400 team_limit_reached
Requests per minute 1,200, of which at most 120 are not GET 429 rate_limited

Amount limits are in whole tokens, not base units. Every supported token is a dollar stablecoin, so 1,000,000 tokens is about $1,000,000.

An invoice is active until it is paid, cancelled or expired. An invoice offered on several networks counts once. A deposit address is active until it is disabled; each network option of a deposit is a separate address. Sandbox and production are counted separately for both limits. Invoise staff can change the invoice, deposit address and team limits for a merchant.

The team limit applies both when inviting and when accepting an invitation. A webhook endpoint’s URL can be changed, so you can reuse an endpoint instead of adding one.

Requests are counted per API key, per dashboard session, or per client IP when unauthenticated. A 429 response carries Retry-After: 60.

Retry timeouts and temporary server errors with the same key, using increasing delays. On 429, wait for the seconds in Retry-After; do not send more requests immediately. Fix invalid input and access errors before retrying.

For webhooks, Invoise retries delivery. Accept the event durably, return 2xx, then process it. Deduplicate by Invoise-Event-ID.

Older /projects routes are aliases of /shops, including their idempotency scope. Use /shops for new integrations. Legacy error names may use project_*.