Events

Send custom events into Ranla to trigger transactional automations.

Base URL: https://api.ranla.ai


Authentication

Authorization: Bearer rnl_…

Dashboard session cookies also work for browser requests to /api/events, which is how the automations canvas editor sends test events.


Trigger an event

POST /events

{
  "name": "user.created",
  "user_id": "user_123",
  "email": "[email protected]",
  "data": {
    "name": "Ada Lovelace",
    "plan": "pro"
  }
}

type is accepted as an alias for name.

Idempotency

Use Idempotency-Key for replay-safe retries:

Idempotency-Key: evt_user_created_123

Retries with the same key and body return the original response. Reusing the key with a different body returns HTTP 409.

Keys are kept for 24 hours. After that, the same key is accepted as a new event, so a key such as user.activated:<userId> does not make an event fire once per person. For once-only events, emit from the moment the state changes (the write that first sets activatedAt), or check a flag your app already stores.

202 Accepted

{
  "event": {
    "id": "ae_123",
    "name": "user.created",
    "user_id": "user_123",
    "email": "[email protected]",
    "data": {
      "name": "Ada Lovelace",
      "plan": "pro"
    },
    "source": "api",
    "created_at": "2026-07-26T12:00:00.000Z"
  },
  "matched_automations": 2,
  "resumed_runs": 1,
  "cancelled_runs": 0
}
  • matched_automations = active automations whose trigger matched this event
  • resumed_runs = waiting runs resumed by this event (wait_for_event)
  • cancelled_runs = active runs cancelled because this event matched trigger.cancel_on_events

Event shape

Field Type Notes
name string Required unless type is provided
type string Alias for name
user_id string Optional identity hint for wait/resume matching
email string Optional identity hint for wait/resume matching
data object Optional event payload used by conditions and email templates
dry_run boolean Dashboard only — with automation_id, runs that one automation even if draft/paused; skips delays/waits and stubs email/SMS
test_send boolean Dashboard only — with automation_id, same targeting as dry-run but sends real email/SMS; still skips delays/waits. Mutually exclusive with dry_run
automation_id string Required with dry_run or test_send; rejected on API-key requests

Inside automations, you can reference:

  • {{event.name}}
  • {{event.email}}
  • {{event.user_id}}
  • {{event.data.foo}}

Credentials in data. Automations triggered by the event see data exactly as you sent it, so a step can mail a login code with {{event.data.code}}. The stored copy of the event is redacted: values under credential keys (password, secret, otp, api_key, anything ending in token, and code on login or verification events such as auth.code_requested), plus secret query parameters inside URL values, are stored as "REDACTED". The event in the response shows the stored copy. Segments and event reports read the stored copy, so they can never match on a credential.


Sign-up source context

A sign-up or trial your server sends (user.created, subscription.started, …) happens away from the browser, so nothing ties it to the visit, ad or campaign that brought the person. Put what your app already knows on the event's data and Ranla credits the conversion to it. Every key is optional.

Key What to send What Ranla does with it
id Your user id on user.created, the subscription id on subscription.started Records the conversion once, however many times the event arrives
visitor_id The stx_vid cookie, read on your server when the account is created (the site snippet sets it on your whole domain) Finds the visits that led to the sign-up, so it gets their channel, campaign and landing page
gclid, gbraid, wbraid The ad click in the rnl_ad cookie (JSON) Credits the conversion to the ad and sends it to Google Ads
came_from Your own word for where they came from: agentid, mcp, cli, outbound, a partner's name Shown as you wrote it beside the measured sources
signup_method password, google, microsoft, invite, … Shown beside each funnel step
invited true when a teammate joins an existing account Kept as an event, counted as a seat, never as a new sign-up
internal true for your own team or a test account Kept as an event, never a conversion

Send subscription.started once per subscription (to the account owner), not once per user on the account. Your workspace's own members, and + aliases of their addresses, are left out of every count without a flag.

// On your server, when the account is created
const cookies = parseCookies(req.headers.cookie)
const ad = JSON.parse(cookies.rnl_ad ?? '{}')
await ranla.events.trigger({
  name: 'user.created',
  email: user.email,
  user_id: user.id,
  data: {
    id: user.id,
    visitor_id: cookies.stx_vid,
    gclid: ad.gclid,
    came_from: 'agentid',
    signup_method: 'google',
  },
  idempotencyKey: `user.created:${user.id}`,
})

Typical flow

  1. Create an automation (dashboard canvas, POST /automations, or supersendtx automations create) with trigger user.created
  2. Activate it (POST /automations/{id} with { "action": "activate" })
  3. Send POST /events from your app when that business event happens
  4. Ranla queues the run in Bull/Redis
  5. Send-email steps flow through the same transactional send path as POST /emails

See also docs/api/automations.md.


SDK

import { Ranla } from '@supersend/ranla'

const client = new Ranla(process.env.RANLA_API_KEY!)

await client.events.trigger({
  name: 'user.created',
  user_id: 'user_123',
  email: '[email protected]',
  data: { name: 'Ada Lovelace' },
  idempotencyKey: 'evt_user_created_123',
})

CLI

RANLA_API_KEY=$RANLA_API_KEY npx -y --package=ranla-cli@latest -- ranla events send \
  --name user.created \
  --email [email protected] \
  --user-id user_123 \
  --data '{"name":"Ada Lovelace"}'

OpenAPI

Machine-readable spec: openapi/supersendtx.yaml