CRISP partners

Authentication and safe retries

Exact HMAC signing, replay protection and financial intent handling.

Sign exact bytes

Using the SDK? It generates these headers automatically. You still own user authorization, credential storage, intent persistence and response handling. Manual signing below is for direct HTTP integrations; it is not an extra setup step required by the SDK.

All integration routes in the catalogue require these headers:

X-Crisp-Partner-Key: cpk_…
X-Crisp-Timestamp: ISO-8601 UTC timestamp
X-Crisp-Nonce: unique nonce, 16–128 characters
X-Crisp-Signature: base64 HMAC-SHA-256

Canonical input (newline separators, no final newline):

timestamp
nonce
UPPERCASE_METHOD
/v1/exact-percent-encoded-path
sha256_hex(raw_body_bytes)

The path includes /v1 and excludes the query string under the current contract. Sign the encoded path actually sent; do not decode and rebuild it. An empty body has the SHA-256 of zero bytes. Serialize JSON once, sign those bytes, and send the same bytes. HTTPS is mandatory; signatures do not replace TLS. The downloadable client implements this format.

Nonce characters: letters, digits, ., _, ~, -; length 16–128. Default timestamp tolerance is five minutes. Nonces are single-use, including GETs. Traffic ingestion is the designated exception: durable deduplication by organization and event ID is used instead of persisting another nonce row. Always generate a fresh nonce.

Idempotency is not authentication

Financial and other durable mutations marked Required in the catalogue need Idempotency-Key: 8–200 letters/digits or ., _, :, -.

  • Persist one intent key before the first submit. Use it for retries of that same path, user and byte-identical body; never recycle it for another intent.
  • Generate new authentication timestamp/nonce/signature for every attempt.
  • A double-click, timeout or 502 does not mean the original action failed.
  • Do not automatically generate a new key to get around an in-progress or ambiguous response. Correct the cause or reconcile the existing action.
  • Quotes, prewarm, realtime sessions and capability minting are not durable money movements and do not require that header. Page views use eventId.

Idempotency responses have retention; do not assume a key is permanent history. Keep your own durable action records. Contact CRISP before retrying an old uncertain financial request whose lifecycle cannot be established.

Responses

{ "data": { "status": "ready" }, "requestId": "request-uuid" }
{ "error": { "code": "account_not_ready", "message": "…", "requestId": "request-uuid" } }
StatusHandling
200Successful read/action; inspect resource state
202Durable acceptance; NOT proof of execution, settlement or final transfer
400Correct invalid fields; do not blindly retry
401Check key, canonical bytes, clock and nonce
403Scope/authority denied; do not retry with another user's identity
404Check account/resource and organization identified by your API key
409Inspect code: in-progress, not-ready, reused nonce, conflict or ambiguous outcome are different cases
429Honor Retry-After; retry with a fresh signature/nonce and the same intent key/body
502/503 or timeoutBack off reads; preserve original financial intent and reconcile before replacement

The example client surfaces errors/statuses and never auto-retries. Log safe request IDs, your intent ID and timestamps, not credentials or entire user payloads.

API limits and overload

Limits are shared across all API keys for your organization’s CRISP integration. The order-cell endpoint uses the same order budget as ordinary order submission. Cancellation capacity is separate from order submission; exhausting an order budget does not consume the cancellation budget.

Default sustained rates are 60 orders/second, 60 cancellations/second, 240 reads/second, 10 reporting requests/second, 10 account provisioning requests/second, 30 other writes/second, 200 traffic events/second and 60 account-update requests/second per organization. These are token-bucket rates with bounded bursts, not a guarantee that every request in a one-second interval will be admitted. Concurrency limits also apply. Confirm your production allocation with CRISP before a load test or traffic increase.

partner_rate_limited and partner_concurrency_limit return 429. Capacity/store/restart errors may return 503, including partner_admission_unavailable, partner_admission_capacity, partner_concurrency_limit, partner_ingress_unavailable and partner_api_draining. These admission responses include Retry-After.

An admission rejection concerns this attempt, not every earlier attempt with the same key. Wait before retrying, retain the original Idempotency-Key and exact body, and generate a new timestamp, nonce and signature. A previous attempt may already be accepted. Never create a replacement financial intent solely because an HTTP request timed out or returned an arbitrary 5xx.

CRISP Partner Documentation