Stream validation events via Server-Sent Events

Download OpenAPI spec
GET /api/v1/events/stream
API key required Base https://api.emailvalidator.ai

Connect to a Server-Sent Events (SSE) stream that delivers validation results in real time. Each event is a JSON-encoded WebhookEnvelope. The stream sends a : heartbeat comment periodically to keep the connection alive.

Population — the stream carries exactly what the list endpoints return for the same key: the key's ACCOUNT (every team member's submissions, not only the key holder's), API-submitted work only (dashboard validations are the dashboard's), and the key's MODE (ev_test_ keys see sandbox events, live keys see live ones). If a verification does not appear in GET /api/v1/verify for a key, it will not appear on that key's stream either — one rule for both.

Reconnection — on disconnect reconnect with Last-Event-ID set to the last received event ID, or ?since=<ISO-8601> to replay events from a specific time. The replay applies the same population rule as the live feed.

Note: this endpoint is not rate-limited (reconnect loops would exhaust a per-minute budget).

Authentication — use the ?api_key= query parameter when a browser EventSource is used (it cannot set custom headers).

On this page

Parameters

query · parameters

ParameterTypeDescription
since string ISO-8601 timestamp or tick count. Returns events after this point. example: 2025-06-10T14:00:00Z

header · parameters

ParameterTypeDescription
Last-Event-ID string SSE reconnect protocol — tick count of the last received event.

Responses

200

SSE stream established. Events are delivered as text/event-stream.

Each event follows the SSE wire format:

id: <ticks>
event: verify.completed
data: <WebhookEnvelope JSON>

Every data: line carries one WebhookEnvelope JSON object — the response schema below is that envelope, not the stream as a whole.

· text/event-stream
401
Missing or invalid API key. · application/json
403
The API key authenticated but is not scoped for this endpoint (code: insufficient_scope). It is a 403 rather than a 401 on purpose — the credential is valid, so retrying with it can never help; a key holding the read scope is needed. · application/json
500
Unexpected server error. The body carries code internal_error plus a request_id to quote in a support request, and never any exception detail. Raised only before the SSE stream has started — once events are flowing the connection simply ends. · application/json

Response schema · 200 · WebhookEnvelope

Wrapper for all webhook deliveries.
FieldTypeDescription
id string Stable, deterministic event ID (evt_ + SHA-256 hex of the resource ID and event name). Identical across retries — use it as your idempotency key. example: evt_3a4b5c6d...
event string Event type. verify.completed batch.completed verify.deleted batch.deleted test example: verify.completed
created_at string · date-time UTC timestamp of the event. example: 2025-06-10T14:02:11.432Z
data object

Event-specific payload:

  • verify.completed — the full Verification object (status: complete).
  • batch.completed — batch summary with pre-signed download URLs. Batches started with a ev_test_ key emit a real signed batch.completed webhook of the same shape (with working pre-signed URLs to the canned result files).
  • verify.deleted / batch.deleted — the deleted resource's id and deleted: true, and nothing else: { "id": … } / { "job_id": … }. Emitted when a result with a registered callback_url is deleted by its owner, so a mirrored copy can be removed in step. No counts, filename, addresses or download URLs — the data they describe no longer exists.
  • test{ "message": "This is a test event." }.

Error responses

401 403 500 · ApiProblem · object

Standard error response shape used by all error status codes.
FieldTypeDescription
status required integer HTTP status code mirrored in the body. example: 400
code required string

The stable, machine-readable error vocabulary. Every ApiProblem.code is one of these values, and this is the WHOLE vocabulary — any one operation emits only the subset its own responses describe.

Branch on this and never on the error prose, which is human-readable and may be reworded at any time. What each code means, the status it arrives with, and whether retrying can help are documented on the Errors page — the same page every error body links to as its doc_url.

Three of these are specific to deletion. result_in_progress refuses to delete a result that is still being produced. insufficient_permissions refuses the ACTOR rather than the key. result_deleted is what a charged Idempotency-Key answers once the result it named has been deleted.

unauthorized invalid_api_key insufficient_scope insufficient_permissions invalid_request invalid_email invalid_callback_url insufficient_credits not_found job_not_pending result_in_progress needs_column_selection too_many_rows unsupported_file_type payload_too_large rate_limited idempotency_in_progress idempotency_key_reuse idempotency_resource_gone result_deleted internal_error example: invalid_email
error required string Human-readable error message. example: Invalid email format.
param string The request field the failure is attributable to. Omitted when the failure is not about one specific field. example: email
details array of string · null Optional per-field validation messages. Null when not applicable. example: ["email: required"]
doc_url string Link to the documentation for this error code. example: https://emailvalidator.ai/docs/get-started/errors
request_id string Correlation id for this request. Quote it in a support request — it is how a single call is found in the server logs. example: 0HNCV1TQ3PLRK:00000003