Public API
Rate limiting & idempotency
A per-key fixed-window rate limit protects shared infrastructure; Idempotency-Key lets your safe retries skip the side effects you already paid for.
Per-key rate limit
Requests are counted per API key on a 1-second sliding bucket. The default ceiling is 80 requests per second; raise or lower it per key in Integrations → API Keys → Advanced. The limit applies across all endpoints — sending messages, listing templates, syncing contacts all consume from the same bucket.
When you exceed the limit:
- HTTP
429with Meta errorcode: 4 - Response header
Retry-Afterwith the number of seconds to wait before the next attempt - No partial side effects — the request is rejected before reaching the business logic
Idempotency-Key
Mutation endpoints (POST, PATCH, PUT) accept an Idempotency-Key request header. SigFollow caches the response for 24 hours on the tuple (api_key.id, idempotency_key). Subsequent identical requests replay the original response without re-executing the handler.
Send a key that is reasonably unique—UUIDv4 works well:
POST /v1/PHONE_NUMBER_ID/messages HTTP/1.1
Host: api.sigfollow.com
Authorization: Bearer sflo_live_xxx
Idempotency-Key: 8c7f0c50-3d8b-4d9e-9b1a-1cb2dc1ba2b4
Content-Type: application/json
{ "messaging_product": "whatsapp", "to": "...", "type": "text", "text": { "body": "Hi" } }The replay carries an additional response header so you can detect it:
HTTP/1.1 200 OK
Idempotency-Replayed: true
Content-Type: application/jsonRules and caveats
- Only successful responses (
2xx) are cached. Failed responses are not cached because the failure may be transient or parameter-related; you should retry without changing the key. - Keys are scoped per
api_key.id. Two different keys with the same idempotency value do not collide. - Keys are not scoped per endpoint path. Reusing the same key across different endpoints will replay an earlier response—use a fresh key per logical operation.
- During in-flight execution, the server holds a 60-second lock on
(api_key.id, idemKey)to prevent double execution. A second request landing while the first is still running is rejected immediately with409 Conflict, body{ "error": "idempotency_in_flight", ... }, and the response headerRetry-After: 1. The caller must back off and retry — the second request does notblock and wait for the winner's response.
GET) the header is ignored—reads are naturally idempotent.Backoff strategy
Recommended retry plan for 429 and 5xx:
attempt 1 → wait 1s
attempt 2 → wait 2s
attempt 3 → wait 4s
attempt 4 → wait 8s
attempt 5+ → wait 16s (cap)
honor Retry-After when presentAlways include the same Idempotency-Key across retries, otherwise a partially-applied call (e.g. message accepted but client timed out) will produce duplicate outbound messages.