On API Call Starter

Prev Next

Suggested readings: Transactional Journeys, Use On API Call Starter

The On API Call starter is the entry point for transactional journeys triggered directly via an API request. It allows backend systems to explicitly enter users into a transactional journey and send messages in real time.

This starter is designed for use cases where message delivery must happen immediately after a system action, without relying on behavioral data or segmentation inside Architect.

Each API request is treated as an explicit instruction to start a journey instance. Common examples include order confirmations, password resets, OTP delivery, shipment notifications, and appointment reminders.

This guide explains the following concepts:

API structure

Trigger endpoint

Transactional journeys using On API Call are triggered via the following endpoint:

POST https://architect.useinsider.com/v1/transactional/send

This endpoint accepts requests that target a specific transactional journey and enqueue users into that journey.

The journey must be in the Active status to accept requests. Requests targeting inactive or non-existing journeys are rejected.

Only one journey can be targeted per request. Up to 100 users can be targeted per request.

Request lifecycle

When a request is sent to the trigger endpoint, Transactional Journeys processes it in the following order:

  1. Authentication: The request is authenticated using partner credentials.

  2. Payload validation: The request body is validated against the required schema.

  3. Rate limiting: Request-level and user-level quotas are enforced.

  4. Idempotency check: Duplicate requests are rejected using the idempotency key.

  5. Journey resolution: The target journey is validated and checked for Active status.

  6. User queuing: Valid users are queued for immediate execution.

Once accepted, journey execution starts asynchronously and is processed within the 30-second end-to-end SLA (service level agreement).

Authentication Requirements

Each request must include the following headers. Requests missing these headers or using invalid credentials are rejected.

X-PARTNER-NAME

X-INS-AUTH-KEY

Content-Type: application/json

You can create an API authentication token for Transactional Journeys via Settings > Integration Settings > API Keys.

Root-level schema:

{
        "idempotency_key": "string",
        "targets": [
        {
        "type": "journey_id",
        "value": number
        }
        ],
        "users": [
        {
        "identifier": {
        "type": "email | phone | iid | uuid",
        "value": "string"
        },
        "dynamic_attributes": { }
        }
        ]
        }

Idempotency behavior

Each request must include a unique idempotency_key. Idempotency is evaluated per request, not per user. It prevents duplicate processing, rejects repeated submissions with the same key, and prevents faulty integration.

If a duplicate key is detected, the request is rejected, and no messages are resent.

Below is an example idempotency key usage:

Order confirmation: order-{order_id}-confirmation
Shipping update: order-{order_id}-shipped
Appointment reminder: appointment-{appointment_id}-reminder

User identification

Each request must include at least one user. Supported identifier types are email, phone number (E.164 format), IID (Insider ID), and UUID (unique user ID).

Each user is evaluated independently. A single request can enter up to 100 users into the journey, meaning that if some users fail validation while others pass, the request is partially accepted.

Rate limits and quotas

Rate limits are enforced at both the request and the user level. The On API Call can process 250 requests per minute and 25,000 users per minute.

Rate limit headers are returned in every response, including remaining quota and retry timing.

If a limit is exceeded, the request is rejected, and no users enter the journey.

Below are rate limit header examples:

X-RateLimit-Limit: 250

        X-RateLimit-Remaining: 245

Dynamic attributes

Dynamic attributes can be sent with the request to personalize message content.

Dynamic attributes:

  • Are available in Email and SMS inner pages.

  • Do not use any value from UCD.

  • Apply only to the current journey entry.

Nested objects

Nested objects are supported up to 3 levels deep. Nested attributes are flattened automatically and can be referenced using dot notation.

Level 1 object→ user name

{
        "idempotency_key": "string",
        "targets": [
        {
        "type": "journey_id",
        "value": 1001
        }
        ],
        "users": [
        {
        "identifier": {
        "type": "email",
        "value": "string"
        },
        "dynamic_attributes": {
        "user": {
        "name": "Sarah"
        }
        }
        }
        ]
        }

Level 2 object→ order.shipping.address

{
        "idempotency_key": "string",
        "targets": [
        {
        "type": "journey_id",
        "value": number
        }
        ],
        "users": [
        {
        "identifier": {
        "type": "email | phone | iid | uuid",
        "value": "string"
        },
        "dynamic_attributes":
        { "order": {
        "shipping": {
        "address": "123 Main St"
        }
        }
        }
        }
        ]
        }

Level 3 object→ order.items.first.name

{
        "idempotency_key": "string",
        "targets": [
        {
        "type": "journey_id",
        "value": number
        }
        ],
        "users": [
        {
        "identifier": {
        "type": "email | phone | iid | uuid",
        "value": "string"
        },
        "dynamic_attributes":
        {
        "order": {
        "items": {
        "first": {
        "name": "Blue Shirt"
        }
        }
        }
        }
        }
        ]
        }

Arrays with nested objects

Level 2 objects and one array index are used →  order.items.0.title

{
        "idempotency_key": "string",
        "targets": [
        {
        "type": "journey_id",
        "value": 1001
        }
        ],
        "users": [
        {
        "identifier": {
        "type": "email",
        "value": "string"
        },
        "dynamic_attributes": {
        "order": {
        "items": [
        {
        "title": "Blue Shirt",
        "sku": "SKU-001"
        }
        ]
        }
        }
        }
        ]
        }

Array indices (index = .0.) don't count toward the 3-level limit.

Below is an invalid example.

Level 4 object -> user.profile.contact.email

{
        "idempotency_key": "string",
        "targets": [
        {
        "type": "journey_id",
        "value": 1001
        }
        ],
        "users": [
        {
        "identifier": {
        "type": "email",
        "value": "string"
        },
        "dynamic_attributes": {
        "user": {
        "profile": {
        "contact": {
        "email": "user@example.com"
        }
        }
        }
        }
        }
        ]
        }

Keep nesting to 2-3 levels for simplicity. Use arrays for collections of items.

Response types

Success responses

HTTP 202 Accepted

{
        "success": true,
        "status": "accepted",
        "users_queued": 1,
        "failed_users": []
        }

HTTP 202 Accepted

Partial success response: only valid users will enter the journey.

{
        "success": true,
        "status": "accepted",
        "users_queued": 3,
        "failed_users": [
        {
        "identifier": {
        "type": "email",
        "value": "invalid-email"
        },
        "error": "schema_validation_failed"
        }
        ]
        }

Failed responses

HTTP 400 Bad Request

{
        "error": "schema_validation_failed",
        "code": 1002,
        "message": "invalid request body",
        "details": {
        "invalid_fields": {
        "users[0].identifier.type": ["must be one of iid phone email uuid"]
        }
        }
        }

Idempotency Conflict - HTTP 400 Bad Request

{
        "error": "idempotency_conflict",
        "code": 3003,
        "message": "idempotency_conflict"
        }

Rate Limit Error - HTTP 429 Too Many Requests

{
        "error": "too_many_requests",
        "code": 2001,
        "message": "too many requests"
        }

Authentication Error - HTTP 401 Unauthorized

{
        "error": "unauthorized",
        "code": 1203,
        "message": "invalid API key"
        }

Server Error - HTTP 500 Internal Server Error

{
        "error": "internal_server_error",
        "code": 3000,
        "message": "unexpected server error"
        }