Documentation

SendStackr API Reference

Trigger workflows, call AI models, track email opens, and ingest webhooks — all via a single API token.

Authentication

All API requests (except /health) require an API workflow token.

1. Create an API token

  1. Sign in to the SendStackr dashboard
  2. Open Project Settings → API Tokens
  3. Click Create Token, give it a name (e.g. "Production"), and optionally set an expiry
  4. Copy the token — it starts with mhk_ and is only shown once

2. Send the token

Include it as a Bearer token in the Authorization header:

Authorization header
Authorization: Bearer mhk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

3. Token scoping

Each token is scoped to a specific project. You can only trigger workflows and access resources within that project. Create separate tokens for development and production environments.

Quick Start

Trigger your first workflow in 2 minutes.

Step 1: Get your workflow ID

Find it in the dashboard URL: /dashboard/projects/PROJECT_ID/workflows/WORKFLOW_ID, or list all workflows via the API:

List workflows
curl -X GET https://api.sendstackr.com/v1/workflows \
  -H "Authorization: Bearer mhk_YOUR_TOKEN"

Step 2: Trigger it

Send a POST with your workflow ID and input data. The response includes a run_id you can use to poll for results.

Trigger a workflow
curl -X POST https://api.sendstackr.com/v1/workflows \
  -H "Authorization: Bearer mhk_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "workflow_id": "550e8400-e29b-41d4-a716-446655440000",
    "input": {
      "from": "[email protected]",
      "subject": "Need help with my order",
      "body": "Hi, I placed order #12345 and haven't received a confirmation."
    }
  }'

Step 3: Check the result

Poll run status
curl -X GET https://api.sendstackr.com/v1/runs/RUN_ID \
  -H "Authorization: Bearer mhk_YOUR_TOKEN"

Workflows

Trigger workflows from your applications. Workflows execute asynchronously — you get a run_id back immediately.

POST
/v1/workflows

Trigger a workflow with custom input data.

Request Body

FieldTypeDescription
workflow_idstring (UUID)The ID of the workflow to trigger. Get it from the dashboard or GET /v1/workflows.
inputobjectKey-value pairs passed to your workflow. Available to nodes as {{ trigger.key_name }} template variables.

Idempotency

Pass an Idempotency-Key header to safely retry without creating duplicate runs. The key is stored for 24 hours.

Response (200)

{
  "status": "ok",
  "run_id": "550e8400-e29b-41d4-a716-446655440099"
}

Input examples by trigger type

Email Received workflow

For workflows with email_received trigger:

{
  "from": "[email protected]",
  "to": "[email protected]",
  "subject": "Question about pricing",
  "body": "Hi, I'd like to know more about the Ultra plan..."
}

Available as {{ Email_Received.from }}, {{ Email_Received.subject }}, {{ Email_Received.body }}

WhatsApp workflow

For workflows with whatsapp_message_received trigger:

{
  "from": "+6281234567890",
  "body": "Halo, saya mau booking villa untuk 15 Agustus"
}
API trigger (OTP / reset password)

For OTP or reset-password template workflows:

OTP email
{
  "to": "[email protected]",
  "otp_code": "849201",
  "expiry_minutes": "10",
  "project_name": "My App"
}
Reset password
{
  "to": "[email protected]",
  "reset_link": "https://myapp.com/reset?token=abc123",
  "expiry_minutes": "60",
  "project_name": "My App"
}
Manual trigger (test run)

For workflows with manual trigger type. Pass any JSON — template variables use {{ Manual_Booking_Payload.body }} etc. depending on the data you send and the first node label in your workflow.

{
  "subject": "Test booking",
  "body": "{\"calendar\":{\"summary\":\"Demo call\",\"start\":\"2026-06-15T14:00:00Z\",\"end\":\"2026-06-15T15:00:00Z\"}}"
}
GET
/v1/workflows

List all workflows accessible with your API token.

Response (200)

{
  "workflows": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Support Reply Flow",
      "trigger_type": "email_received",
      "enabled": true,
      "created_at": "2026-05-15T08:00:00Z",
      "updated_at": "2026-06-01T12:30:00Z"
    }
  ]
}
GET
/v1/workflows/{workflow_id}

Get a single workflow with full detail including node graph and settings.

Path Parameters

ParameterDescription
workflow_idThe workflow UUID

Run Status

After triggering a workflow, poll the run endpoint to check its status and get step-by-step outputs.

GET
/v1/runs/{run_id}

Get the status and output of a workflow run.

Response (200)

{
  "id": "550e8400-...-00099",
  "workflow_id": "550e8400-...-00000",
  "status": "completed",
  "input": {
    "from": "[email protected]",
    "subject": "Need help with my order",
    "body": "Hi, I placed order #12345..."
  },
  "steps": [
    {
      "node_id": "n1",
      "node_type": "email_received",
      "label": "Email Received",
      "status": "completed",
      "output": {},
      "started_at": "2026-06-01T12:30:00Z",
      "completed_at": "2026-06-01T12:30:00Z"
    },
    {
      "node_id": "n2",
      "node_type": "ai_analysis",
      "label": "AI Analysis",
      "status": "completed",
      "output": {
        "result": "Customer is asking about order #12345..."
      },
      "started_at": "2026-06-01T12:30:01Z",
      "completed_at": "2026-06-01T12:30:03Z"
    },
    {
      "node_id": "n4",
      "node_type": "send_email",
      "label": "Send Email",
      "status": "completed",
      "output": { "sent": true },
      "started_at": "2026-06-01T12:30:03Z",
      "completed_at": "2026-06-01T12:30:04Z"
    }
  ],
  "started_at": "2026-06-01T12:30:00Z",
  "completed_at": "2026-06-01T12:30:04Z"
}

status values: running · completed · failed · cancelled

GET
/v1/runs

List recent runs, optionally filtered by workflow ID or status.

Query Parameters

ParameterTypeDescription
workflow_idUUIDFilter by specific workflow
statusenumFilter: running, completed, or failed
limitintegerMax results (default 20, max 100)

Chat Completions (OpenAI Compatible)

Drop-in replacement for the OpenAI chat completions endpoint. Use your SendStackr API token in place of an OpenAI key. Supports streaming, multi-modal (images), and agentic RAG.

POST
/v1/chat/completions

OpenAI-compatible chat completion with optional RAG augmentation.

Supported Models

  • gpt-4o — most capable
  • gpt-4o-mini — fast, cost-effective
  • claude-sonnet-4-20250514 — Anthropic
  • gemini-2.5-flash — Google
  • Any model enabled in your project's AI provider settings

Agentic RAG

Send the header x-agentic-rag: true to automatically augment each request with relevant context from your project's knowledge base. No additional code required — the RAG pipeline handles document retrieval and context injection.

Non-streaming request

curl -X POST https://api.sendstackr.com/v1/chat/completions \
  -H "Authorization: Bearer mhk_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [
      {"role": "system", "content": "You are a helpful customer support agent."},
      {"role": "user", "content": "What is your return policy?"}
    ],
    "max_tokens": 256
  }'

Non-streaming response

{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "model": "gpt-4o-mini",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Our return policy allows returns within 30 days..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 45,
    "completion_tokens": 120,
    "total_tokens": 165
  }
}

Streaming

Set "stream": true to receive Server-Sent Events:

data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Our"},"finish_reason":null}]}

data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":" return"},"finish_reason":null}]}

data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: [DONE]

Webhooks (Inbound)

Ingest events from external platforms — Stripe, Paymentku, Shopify, custom CRM — into your workflows.

POST
/v1/webhooks/{project_id}

Receive events from external platforms. Matched against your workflow trigger conditions.

Setup

  1. Find your project ID in the dashboard URL
  2. Set your webhook URL in the external platform: https://api.sendstackr.com/v1/webhooks/YOUR_PROJECT_ID
  3. Optionally set a shared secret in Project Settings → Webhooks for HMAC verification

Signature Verification

When a shared secret is configured, include the x-webhook-signature header with the HMAC-SHA256 hex digest of the raw request body:

x-webhook-signature: SHA256(payload + secret)

Example payloads

Stripe payment
{
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "id": "pi_3NxEXAMPLE",
      "amount": 2999,
      "currency": "usd",
      "metadata": { "order_id": "ord_789" }
    }
  }
}
Paymentku webhook
{
  "type": "payment.success",
  "data": {
    "trx_id": "PKU-20260525-001",
    "amount": "150000",
    "status": "paid",
    "customer_email": "[email protected]"
  },
  "timestamp": "2026-05-25T11:51:31Z",
  "signature": "hmac_sha256_hex_digest"
}
Custom CRM event
{
  "event": "lead.created",
  "lead": {
    "email": "[email protected]",
    "source": "website_form",
    "score": 85
  }
}

Email Open Tracking

Track when recipients open your emails with a 1×1 transparent GIF pixel.

GET
/v1/pixel/{workflow_id}.gif

Returns a 1×1 transparent GIF and records the email open event.

How to use

Embed this image tag anywhere in your HTML email:

<img
  src="https://api.sendstackr.com/v1/pixel/WORKFLOW_ID.gif?token=mhk_YOUR_TOKEN&[email protected]"
  width="1"
  height="1"
  alt=""
/>

Query Parameters

ParameterRequiredDescription
tokenYesYour mhk_* API token
toNoRecipient email for analytics

What happens

When the pixel loads, the API records the open event (including user agent and IP) and fires the email_opened trigger on matching project workflows. The pixel always returns successfully — it never breaks email rendering.

Enable this in your workflow by adding an email_opened trigger node in the workflow builder, then use the workflow's ID in the pixel URL.

Usage & Limits

Monitor your token consumption and plan limits.

GET
/v1/usage

Get daily and monthly token usage plus plan limits.

Response (200)

{
  "daily_used": 12450,
  "monthly_used": 87650,
  "daily_limit": null,
  "monthly_limit": 100000,
  "is_suspended": false
}

daily_limit / monthly_limit are null when unlimited.is_suspended is true when you've exceeded your plan limits.

Rate Limits

EndpointLimit
Chat completions60 requests per minute
Workflow triggers120 requests per minute
Webhook ingestionBackground job (no rate limit)

Exceeding a limit returns 429 Too Many Requests with a Retry-After header.

Error Handling

All error responses follow the same structure:

{
  "error": "bad_request",
  "message": "workflow_id is required",
  "details": {},
  "request_id": "req_Xa7Bc9Dd3Ee"
}

Error Codes

StatusCodeMeaning
400bad_requestMissing or invalid parameters
401unauthorizedMissing, expired, or invalid API token
402payment_requiredInsufficient credits for the request
404not_foundWorkflow or run not found
429rate_limitedRate limit exceeded — check Retry-After header
500internal_errorServer error — include request_id when contacting support