Documentation

Conversions

Count the events that matter, such as a subscription or a purchase, and credit each one to the email that earned it.

A conversion goal names an event your app already sends, such as subscription_started. From the moment the goal exists, every event with that name is also recorded as a conversion and credited to the last email the person clicked within the goal's window (7 days unless you choose otherwise). Campaign, A/B variant and automation step reports then show conversions, converters and revenue beside opens and clicks.

How the credit is decided:

  • Last click. The conversion goes to the most recent email the person clicked before it, within the window. It is a rule you can predict and check, and the one most email tools use.
  • Only a person's click. Corporate security gateways open every link in a message within a second of delivery. Those clicks are recognised and never earn credit, so a scanner cannot claim a sale.
  • Opens never count. Apple Mail fetches every image when a message arrives, so an "open" there says nothing about a person.
  • Attributed, not caused. A credited email is the last one the person clicked. It is not proof the email made them buy, and the dashboard says "attributed" for that reason.

A conversion starts pending and is credited a few seconds after it arrives, once every click that could earn it has been checked for scanners. With no click by a person in the window it becomes unattributed: it is kept and listed, and counted in no report. Events received before a goal existed are not counted.

Create a conversion goal

POST /v1/conversion-goals · requires broadcasts:write

Body

FieldTypeRequiredDefaultDescription
event_namestringyes1 to 120 characters, matched exactly (including case) against name on POST /v1/events.
window_daysintegerno71 to 30. How many days before the conversion a click may be and still earn the credit.

A workspace can have up to 50 goals.

Example

curl -X POST https://api.sendraven.ai/v1/conversion-goals \
  -H "Authorization: Bearer $SENDRAVEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "event_name": "subscription_started", "window_days": 7 }'

Response

201 Created

{
  "id": "3f6c1a52-8a0e-4c3e-9b1f-2d7e5a9c4b10",
  "event_name": "subscription_started",
  "window_days": 7,
  "created_at": "2026-10-29T12:00:00.000Z"
}

Errors

StatusTypeWhen
409conflictThis event name is already a goal. List goals shows it with its id.
422invalid_requestThe body failed validation, or the workspace already has 50 goals.

List conversion goals

GET /v1/conversion-goals · requires broadcasts:read

Every goal, oldest first, in the list envelope. Not paged: next_cursor is always null.

Retrieve a conversion goal

GET /v1/conversion-goals/{id} · requires broadcasts:read

Answers the goal, or 404 not_found.

Change a goal's window

PATCH /v1/conversion-goals/{id} · requires broadcasts:write

Takes window_days (1 to 30) and nothing else. The new window applies to conversions not yet credited. One already credited keeps its email, so a report never changes under someone reading it. The event name cannot change; create a new goal instead.

Delete a conversion goal

DELETE /v1/conversion-goals/{id} · requires broadcasts:write

Deletes the goal and every conversion recorded against it. They cannot be restored. The event keeps working as an ordinary event, and automations it starts are unaffected.

{ "id": "3f6c1a52-8a0e-4c3e-9b1f-2d7e5a9c4b10", "deleted": true, "conversions_deleted": 41 }

Record a conversion

Send the goal's event to POST /v1/events, with value and currency when there is an amount and your own id so a repeat is counted once:

curl -X POST https://api.sendraven.ai/v1/events \
  -H "Authorization: Bearer $SENDRAVEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "subscription_started", "email": "ana@example.com", "id": "in_1Q2w3E", "value": 49, "currency": "USD" }'

The response's conversion_id names the conversion.

Conversion metrics

GET /v1/conversions/metrics · requires broadcasts:read

Credited conversions, distinct converters and revenue per currency. Scoped to one campaign it adds the messages sent and the conversion rate, and a row per variant for an A/B test. Scoped to one automation, a row per step.

The rate is converters / sent: it counts people, so one reader buying twice does not double it. Revenue counts every purchase. Values in different currencies are never added together. Pending and unattributed conversions are not counted.

Query parameters

ParameterDescription
goal_idOnly this goal. All goals when left out.
broadcast_idOnly conversions credited to this campaign. Not with automation_id.
automation_idOnly conversions credited to this automation. Not with broadcast_id.
from, toISO 8601 times. Conversions received at or after from and before to.

Response

200 OK, for an A/B test campaign:

{
  "goal_id": null,
  "broadcast_id": "8b1d…",
  "automation_id": null,
  "from": null,
  "to": null,
  "conversions": 52,
  "converters": 48,
  "revenue": [{ "currency": "USD", "amount": 2548 }],
  "sent": 10000,
  "conversion_rate": 0.0048,
  "by_variant": [
    { "key": "short", "conversions": 30, "converters": 28, "revenue": [{ "currency": "USD", "amount": 1470 }], "sent": 1000, "conversion_rate": 0.028 },
    { "key": "question", "conversions": 22, "converters": 20, "revenue": [{ "currency": "USD", "amount": 1078 }], "sent": 1000, "conversion_rate": 0.02 }
  ],
  "by_step": null
}

sent and conversion_rate are null unless broadcast_id or automation_id is given. by_variant is null unless the campaign is an A/B test, and by_step unless automation_id is given. A step row has step (its position now, numbered from 1) and step_id in place of key. Figures follow the step id, so a step keeps its own conversions when the sequence is edited; automation_step on a conversion is the position when the email was sent.

Errors

StatusTypeWhen
404not_foundgoal_id, broadcast_id or automation_id names nothing in the workspace.
422invalid_requestA filter is malformed, or both broadcast_id and automation_id were given.

List conversions

GET /v1/conversions · requires broadcasts:read

Every recorded conversion, newest first, paged with limit and cursor. Takes the metrics filters above, plus status (pending, attributed or unattributed) and email for one person's conversions.

Retrieve a conversion

GET /v1/conversions/{id} · requires broadcasts:read

Response

{
  "id": "c41e…",
  "goal_id": "3f6c1a52-8a0e-4c3e-9b1f-2d7e5a9c4b10",
  "event_name": "subscription_started",
  "email": "ana@example.com",
  "external_id": "in_1Q2w3E",
  "value": 49,
  "currency": "USD",
  "status": "attributed",
  "occurred_at": "2026-10-29T12:04:10.000Z",
  "message_id": "5a2f…",
  "clicked_at": "2026-10-28T09:12:44.000Z",
  "broadcast_id": "8b1d…",
  "variant": "short",
  "automation_id": null,
  "automation_step": null,
  "automation_step_id": null,
  "attributed_at": "2026-10-29T12:04:22.000Z"
}

message_id, clicked_at, broadcast_id, variant, automation_id, automation_step and automation_step_id are set only when status is attributed, and each is null when it does not apply. A transactional email can be credited too; it has no campaign or automation.

On this page