Ricky logorickyDocs

Idempotency, rate limits and retries

Repeat writes without duplicating effects, and stay within the request limit.

Idempotency-Key

Writes that change contacts or conversations, or that send messages, require the Idempotency-Key header. With it, repeating a request does not repeat its effect: a message is not sent twice and a contact is not created twice.

OperationEndpointScope
Create a contactPOST /contactscontacts:write
Update a contactPATCH /contacts/{contact_id}contacts:write
Start a conversationPOST /conversationsmessages:send
Assign a conversationPATCH /conversations/{conversation_id}/assignmentconversations:write
Close a conversationPOST /conversations/{conversation_id}/closeconversations:write
Reopen a conversationPOST /conversations/{conversation_id}/reopenconversations:write
Send a messagePOST /conversations/{conversation_id}/messagesmessages:send

Creating or disabling a webhook and retrying a delivery do not use this header.

Rules

  • Generate a unique value for each logical write, for example a UUID v4. It must be 8 to 200 characters long.
  • The idempotency key is scoped to your API key. Another API key can use the same value without conflict.
  • Ricky compares the method, the path and the body. Repeat all three exactly when you retry.
  • Without the header, or with a value out of range, the response is 400 missing_idempotency_key.
  • Ricky validates the request before it reads the header. An invalid body or a conversation that does not exist gets its own error even if the header is missing.
curl https://getricky.ai/api/v1/contacts \
  -H "Authorization: Bearer $RICKY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed" \
  -d '{"first_name": "Ana", "last_name": "Pérez", "primary_phone": "+507 6000-1234"}'

What Ricky answers when a key repeats

First attemptRepeat with the same key and the same request
Ended with 2xxThe same response and status, with the Idempotency-Replayed: true header. No new effect.
Still processing409 request_processing with Retry-After: 5.
Ended with 4xxRicky releases the key. The repeat is processed as a new request.
Ended with 5xx or without a response409 request_processing. The effect may or may not have happened.

The same key with another method, another path or another body gets 409 idempotency_conflict.

Unknown state

After a 5xx, Ricky does not know whether the effect happened, so the same key keeps answering 409 request_processing. Do this:

  1. Read the resource to learn whether the write happened. For example, after sending a message, list the conversation's messages.
  2. If it happened, do nothing else.
  3. If it did not happen, repeat the write with a new Idempotency-Key.

A new key always creates a new effect. Use one only when you know the first attempt did not happen. If you cannot tell, contact support with the X-Request-Id.

Rate limit

Each API key allows 120 requests per minute. The window is the clock minute: it resets at second 0 of every minute.

Every response to a valid key, success or error, includes:

HeaderValue
X-RateLimit-LimitRequests per minute: 120.
X-RateLimit-RemainingRequests left in the current minute.
X-RateLimit-ResetUnix time, in seconds, when the window resets.

Over the limit, the response is 429 rate_limited with Retry-After, in seconds, and the same X-RateLimit-* headers. Wait that long before sending another request with that key.

If you need to process many records, spread the requests over time and read X-RateLimit-Remaining before each batch.

Retries

Retry only what can succeed unchanged. Wait longer between attempts: exponential backoff with random jitter, for example 1, 2, 4, 8 and 16 seconds, up to 5 attempts. If the response carries Retry-After, wait at least that long.

ResponseRead (GET)Write with Idempotency-Key
Network error or timeoutRetry.Retry with the same key.
429 rate_limitedRetry after Retry-After.Retry with the same key after Retry-After.
409 request_processingDoes not apply.Retry with the same key after Retry-After. If it persists, follow Unknown state.
500, 502 or 503Retry.Follow Unknown state.
Any other 4xxFix the request.Fix the request.

On this page