Skip to content
Not available yet. Replyz is built and tested, but not deployed: https://api.replyz.io is the planned address and does not answer yet. These pages describe the API as it is built today and may change before launch.

Events

An ordered feed of what happens in the account, for polling or long-polling. The only event type today is message.received.

GET /v1/events

Auth: API key (Authorization: Bearer rz_live_…)

Returns the events whose sequence number is greater than after, oldest first. Keep next_after and pass it as after next time to get only new events. The only event type today is message.received; ignore types you do not know.

  • With wait above 0 and no new events, the request is held for up to wait seconds and returns as soon as an event arrives. Held requests share the limit of 5 per account with GET /v1/inboxes/{id}/wait (429 too_many_waits).
  • status is timeout whenever no events are returned (also with wait=0); next_after then equals after.
  • Sequence numbers increase but can have gaps: events of deleted inboxes are hidden.
  • Events carry ids and a little metadata only; read the message itself with GET /v1/messages/{id}. Reading events does not mark messages as read.
  • For an expired or suspended account (including a sandbox account past its expires_at) the call never holds: wait is still validated, then treated as 0.

Problem codes: unauthorized (401), invalid_request (400), too_many_waits (429).

Name In Type Required Description
after query integer (0–9007199254740991, default 0) no Return only events with a larger seq. Use the next_after of the previous call.
wait query integer (0–60, default 0) no Seconds to hold the request while there are no new events. 0 (the default) answers at once. Validated for every account, but treated as 0 for an expired or suspended account.
limit query integer (1–100, default 100) no Maximum number of events returned.

Events after after, oldest first, or none (status is then timeout).

Content type application/json.

Field Type Required Description
status string: ok, timeout yes ok: at least one event. timeout: no events were returned.
events array of Event (max 100 items) yes Oldest first.
events[].seq integer (1–) yes Sequence number, increasing within the account (it can have gaps).
events[].type string yes The event type. Only message.received exists today; ignore types you do not know.
events[].created_at string (date-time) yes When the event happened (for message.received, when the message was received).
events[].data MessageReceivedEventData yes Event data; its shape depends on type.
events[].data.message_id string yes
events[].data.inbox_id string yes
events[].data.thread_id string yes
events[].data.from string or null yes As in the message. Not verified.
events[].data.subject string or null yes As in the message. Untrusted.
events[].data.otp_like boolean yes
events[].data.sender_trust string: aligned_pass, dkim_pass, unauthenticated yes How far the sender is authenticated. Today every message is unauthenticated: aligned_pass and dkim_pass are planned (docs/features/safety.md). They will be based on Cloudflare’s own authentication results, located by position; ambiguous cases are unauthenticated.

- aligned_pass: Cloudflare reports a DMARC pass for the domain of from. The mail comes from that domain; its content is still untrusted.
• dkim_pass: Cloudflare reports a valid DKIM signature but no DMARC pass. The signature can belong to any domain, so from can still be forged.
• unauthenticated: everything else. from can be forged.

A message that could not be parsed is always unauthenticated.
next_after integer (0–) yes The after value for the next call (the last event’s seq, or after unchanged when there were none).

Example: Two new messages (after=1)

{
"status": "ok",
"events": [
{
"seq": 2,
"type": "message.received",
"created_at": "2026-11-06T10:31:05.902Z",
"data": {
"message_id": "msg_01M6R6JZDERMT2DVG0T8ABTX4J",
"inbox_id": "ibx_01M6R4T180ZADNV1160NS1SRNP",
"thread_id": "thr_01M6R6JZDERMT2DVG0T8ABTX4J",
"from": "ana@example.com",
"subject": "Dinner on Friday?",
"otp_like": false,
"sender_trust": "unauthenticated"
}
},
{
"seq": 3,
"type": "message.received",
"created_at": "2026-11-06T10:47:40.117Z",
"data": {
"message_id": "msg_01M6R7HAANT4D11FHFZPYG0C2V",
"inbox_id": "ibx_01M6R4T180ZADNV1160NS1SRNP",
"thread_id": "thr_01M6R6JZDERMT2DVG0T8ABTX4J",
"from": "ana@example.com",
"subject": "Re: Dinner on Friday?",
"otp_like": false,
"sender_trust": "unauthenticated"
}
}
],
"next_after": 3
}

Example: No new events (after=3)

{
"status": "timeout",
"events": [],
"next_after": 3
}

invalid_request: a query parameter is invalid (after is not an integer from 0 to 9007199254740991, wait is not an integer from 0 to 60, or limit is not an integer from 1 to 100). The message names the parameter.

Problem object (application/problem+json). Codes: invalid_request.

Example: invalid_request: after

{
"type": "https://docs.replyz.io/errors/invalid_request",
"code": "invalid_request",
"status": 400,
"message": "Invalid query parameter \"after\".",
"fix": "Use an integer from 0 to 9007199254740991.",
"docs": "https://docs.replyz.io/errors/invalid_request.md"
}

Example: invalid_request: wait

{
"type": "https://docs.replyz.io/errors/invalid_request",
"code": "invalid_request",
"status": 400,
"message": "Invalid query parameter \"wait\".",
"fix": "Use an integer from 0 to 60.",
"docs": "https://docs.replyz.io/errors/invalid_request.md"
}

unauthorized: the Authorization header is missing, is not Bearer rz_live_…, or holds an unknown or revoked key.

Header Description
WWW-Authenticate Always Bearer realm="replyz".

Problem object (application/problem+json). Codes: unauthorized.

Example: unauthorized: missing or malformed key

{
"type": "https://docs.replyz.io/errors/unauthorized",
"code": "unauthorized",
"status": 401,
"message": "Missing or malformed API key.",
"fix": "Send the header Authorization: Bearer rz_live_… with the api_key from POST /v1/signup.",
"docs": "https://docs.replyz.io/errors/unauthorized.md"
}

too_many_waits: the account already holds 5 long-polls (wait and events?wait= together). Wait for one to return, or call without holding.

Header Description
Retry-After Always 1.

Problem object (application/problem+json). Codes: too_many_waits.

Example: too_many_waits

{
"type": "https://docs.replyz.io/errors/too_many_waits",
"code": "too_many_waits",
"status": 429,
"message": "This account already has 5 long-polls open (wait and events share the limit).",
"fix": "Wait for one of them to return before starting another, or poll without holding (wait: timeout=0; events: wait=0).",
"docs": "https://docs.replyz.io/errors/too_many_waits.md"
}

internal_error: something failed on Replyz’s side. Retry after a few seconds.

Problem object (application/problem+json). Codes: internal_error.

Example: internal_error

{
"type": "https://docs.replyz.io/errors/internal_error",
"code": "internal_error",
"status": 500,
"message": "Something went wrong on our side.",
"fix": "Retry in a few seconds.",
"docs": "https://docs.replyz.io/errors/internal_error.md"
}