Conventions
Patterns that apply across every endpoint. Read this once and the rest of the reference reads cleaner.
Idempotency
Any state-mutating request (POST, PATCH, DELETE) accepts an Idempotency-Key header. Re-sending the same request with the same key returns the original response — safe to retry.
curl -X POST https://api.bequest.org/v1/gifts \
-H "Authorization: Bearer $BQ_KEY" \
-H "Idempotency-Key: req_8x9..." \
-d '{"from":"usr_8f3...","to":"org_a91...","amount_cents":2500}'
Idempotency keys are remembered for 24 hours. After that, the same key represents a new request.
Pagination
List endpoints return up to 25 records by default. Use limit (max 100) and cursor for paging.
GET /v1/gifts?limit=50&cursor=eyJpZCI6Imdmd...
{
"data": [ ... ],
"has_more": true,
"next_cursor": "eyJpZCI6Imdmd..."
}
Money
All amounts are integer cents in USD unless a currency field is specified. We never use floats.
Timestamps
All timestamps are RFC 3339 UTC. Example: 2026-05-15T13:45:09Z.
Errors
Every error response is JSON with a stable error.type code.
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"error": {
"type": "validation_failed",
"message": "amount_cents must be at least 50.",
"field": "amount_cents",
"request_id": "req_8x9..."
}
}
Common error.type values:
auth_invalid— bad or revoked key.rate_limited— back off and retry per theRetry-Afterheader.validation_failed— one or more fields didn't pass schema.idempotency_conflict— same key, different body.resource_not_found— id doesn't exist or you can't see it.internal_error— something failed on our side. Includesrequest_id— send it to support.
Request IDs
Every response carries an X-Request-Id header. If you ever email support, paste it.