Skip to content

Requests and errors ​

Base URL and format ​

All endpoints are under https://api.sealreply.com/v1. Send and receive JSON (Content-Type: application/json). Times are ISO 8601 in UTC. IDs are UUIDs; message IDs sort by time.

Every response is an envelope:

json
{ "success": true, "data": { … }, "error": null }

Errors ​

On failure success is false, data is null, and error explains:

json
{
  "success": false,
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Some fields are invalid. Please check and try again.",
    "fields": { "email": "invalid" },
    "request_id": "req_01a1…"
  }
}

Program against code; message is for people and follows the Accept-Language header. Quote request_id when you contact support.

CodeStatusMeaning
bad_request400The request could not be read.
validation_failed422A field is invalid; fields names it and why.
unauthorized401Missing, unknown or revoked key.
forbidden403The key lacks the scope (fields.scope), or the endpoint is not open to keys.
tenant_suspended403The workspace is suspended.
not_found404No such resource in your workspace.
conflict409Changed meanwhile, or the same Idempotency-Key is still being handled.
conversation_closed409The conversation has ended.
rate_limited429Too many requests; wait Retry-After seconds.
quota_exceeded402A plan limit is reached; fields.limit says which.
plan_upgrade_required402Your plan lacks the feature; fields.feature says which.
internal500Our fault. Safe to retry.

Pagination ​

Lists return up to limit items (default 20, at most 100) and a cursor:

json
{ "data": [ … ], "meta": { "has_more": true, "next_cursor": "MjAyNi0…" } }

Pass cursor=<next_cursor> for the next page until has_more is false. Conversation lists are newest activity first; message history pages backwards from the newest.

Retrying safely ​

  • Messages: give every message a client_msg_id you generate (a UUID). Sending again with the same one returns the first message instead of a duplicate.
  • Any write: send an Idempotency-Key header (up to 255 characters). For 24 hours, repeating the same request returns the first successful response with Idempotent-Replayed: true. Reusing a key for a different body returns 422 with fields.Idempotency-Key = reused; a repeat while the first is still running returns 409 conflict. Failed responses are not stored, so you can retry them.

Unknown fields ​

Responses and webhook bodies may gain new fields and new enum values over time. Ignore the ones you do not know rather than failing on them.