API conventions

Three rules hold for every endpoint: writes can be retried safely, lists page with cursors, and errors always have the same shape.

Idempotency keys

Send an Idempotency-Key header with any POST. If the same key arrives again within 24 hours, you get the original result back and the work is not done twice. Use a new UUID for each distinct action.

curl -X POST "$BASE/conversations/cnv_7Hq2Lm/reply" \
  -H "Authorization: Bearer $GRIPZ_API_KEY" \
  -H "Idempotency-Key: 6f1c2a9e-4b7d-4e0a-9a3e-2d5b8c1f7a40" \
  -H "Content-Type: application/json" \
  -d '{ "body": "Your refund is on its way." }'

Cursors

List endpoints return 50 items by default and 200 at most. Pass next_cursor back as cursor to get the next page. Cursors are opaque, so do not parse or build them.

GET /v1/contacts?limit=50&cursor=cur_9aK2mQ

{
  "data": [ { "id": "ct_9d3m", "name": "Elena Marchetti" } ],
  "has_more": true,
  "next_cursor": "cur_Lp41xT"
}

Error format

Every error has a type, a stable code, a message written for a person, and a request ID you can quote to support.

{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "limit must be between 1 and 200.",
    "param": "limit",
    "doc_url": "https://developers.gripz.example/rest/conventions#cursors",
    "request_id": "req_8F2KQ41Z"
  }
}
Error fields
typeThe family: invalid_request_error, authentication_error, permission_error, rate_limit_error or api_error.
codeA stable string to branch on in code. Codes are never renamed within a version.
request_idAlso sent as the Gripz-Request-Id header on every response, including successes.