Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.formo.so/llms.txt

Use this file to discover all available pages before exploring further.

Public unsafe methods (POST / PUT / PATCH / DELETE on /v0/*) honour an optional Idempotency-Key header. When present, Formo de-duplicates retries so a flaky network or a crashed client never causes a double-write. The header is opt-in — omit it and every request is processed independently.

How it works

POST /v0/alerts HTTP/1.1
Host: api.formo.so
Authorization: Bearer formo_…
Idempotency-Key: 8a3a2b1e-7c4d-4a5e-9c2f-1f8a3a2b1e9f
Content-Type: application/json

{ "name": "Daily revenue drop", "trigger_type": "event", "...": "..." }
  • The first request runs normally; the response (status code + body) is cached for 24 hours under idem:{teamId}:{projectId}:{key} along with a fingerprint of the request (method + full mount path + body).
  • Subsequent requests with the same key and matching fingerprint replay the cached response byte-for-byte — retries can never double-create or double-charge.
  • The cache is scoped to projectId as well as teamId, so two project-scoped API keys in the same workspace can use the same key without colliding.

What gets cached

OutcomeCached?Why
2xx successReplay the original result — that’s the whole point.
5xx server errorIf the server failed transiently after partially executing, a retry should see the same failure rather than risk double-execution.
4xx client errorValidation failures aren’t recorded. A corrected retry under the same key runs normally.
The in-flight lock is also released on 4xx so a corrected retry under the same key can proceed immediately.

Failure modes

400 INVALID_IDEMPOTENCY_KEY — key reused for a different request

Reusing the same key for a different operation (different method, path, or body) returns 400 INVALID_IDEMPOTENCY_KEY. This prevents silent dropped writes when a client accidentally reuses a key across distinct requests. Also returned if the key exceeds 255 characters.

409 IDEMPOTENCY_IN_PROGRESS — concurrent retry

Two concurrent requests with the same key in flight return 409 IDEMPOTENCY_IN_PROGRESS. Wait briefly (typically under 1 second) and replay — the server will return the cached response of the original request.

Redis outage

If the idempotency cache (Redis) is unavailable, the request runs without caching — Redis outages don’t block writes. Concurrent retries during such an outage may double-execute; the contract is best-effort.
  1. Generate a fresh UUID v4 per logical operation. Don’t reuse keys across different actions, even if the body looks similar.
  2. Persist the key before the first attempt. Save it to disk / DB before calling the API so an in-flight crash doesn’t lose it. On restart, retry with the same key.
  3. Scope to a single workspace. Two API keys for different projects can safely share an idempotency key — but don’t rely on that; scope per workspace anyway.
  4. Pair with retry-with-backoff for 429 / 503 / 5xx. Idempotency makes those safe to replay.
  5. Maximum length: 255 characters. Use a UUID v4 (36 chars) or any random ≤255-char string.

Examples

curl -X POST https://api.formo.so/v0/alerts \
  -H "Authorization: Bearer formo_…" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Daily revenue drop",
    "trigger_type": "event",
    "trigger_filters": [
      { "name": "event", "operator": "equals", "value": "transaction" }
    ],
    "recipient": [{ "type": "email", "value": ["alerts@myapp.com"] }]
  }'
See Errors for the full list of error codes and remediation guidance.