Skip to main content
Not every tool in your stack will have a native Stairoids integration — and that’s fine. The Stairoids REST API gives you a direct path to push signals in from any source and receive action triggers out via webhooks. Whether you’re connecting an internal data warehouse, a niche sales tool, or wiring things together with a no-code platform like n8n, Make, or Zapier, the Custom API integration is how you do it.

Two integration patterns

Use the POST /v1/signals endpoint to send a signal into Stairoids from any tool, script, or automation platform. This is the right pattern when your tool generates an event you want Stairoids to act on — for example, a product usage event, a form submission from a tool not natively integrated, or a custom intent signal from your data warehouse.When to use this pattern:
  • Your tool supports outgoing webhooks or HTTP requests
  • You’re using n8n, Make, or Zapier to relay events from a third-party tool
  • You’re writing a custom script or backend service that generates events
Authentication uses a Bearer token. Generate your API key under Settings → API Keys → Create API Key.

Example 1 — Push a signal in

Request

Send a POST request to https://api.stairoids.com/v1/signals with a JSON body describing the signal event.
curl -X POST https://api.stairoids.com/v1/signals \
  -H "Authorization: Bearer sk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "product_trial_started",
    "source": "internal_app",
    "account": {
      "domain": "acmecorp.com",
      "name": "Acme Corp"
    },
    "contact": {
      "email": "jane.doe@acmecorp.com",
      "first_name": "Jane",
      "last_name": "Doe"
    },
    "properties": {
      "plan": "pro_trial",
      "trial_ends_at": "2024-09-15T00:00:00Z",
      "invited_by": "sales_outreach"
    }
  }'

Request body fields

FieldTypeRequiredDescription
typestringThe signal event type. Use any descriptive string for custom events.
sourcestringAn identifier for the system sending the signal (e.g., "internal_app", "zapier", "n8n").
account.domainstringRecommendedThe company domain. Used for account matching in Stairoids.
account.namestringThe company name. Used if no existing account matches the domain.
contact.emailstringRecommendedThe contact’s email address. Used for contact matching.
contact.first_namestringContact’s first name.
contact.last_namestringContact’s last name.
propertiesobjectAny additional key-value pairs relevant to the signal. Accessible in automation conditions and action templates.

Response

A successful signal submission returns 201 Created:
{
  "id": "sig_01j4k8m2n3p5q6r7s8t9u0v1",
  "type": "product_trial_started",
  "source": "internal_app",
  "status": "received",
  "account_id": "acc_01j4k8m2n3p5q6r7",
  "contact_id": "con_01j4k8m2n3p5q6r8",
  "created_at": "2024-09-01T14:32:00Z"
}
You can use any string value for the type field when sending custom signals — there is no required list. Use descriptive names that reflect the event in your system, such as "product_trial_started", "demo_requested", or "invoice_overdue". These type strings become available as trigger conditions in Stairoids automations immediately after the first signal of that type is received.

Example 2 — Receive a webhook action trigger

When a Stairoids automation fires an outgoing action of type Webhook, Stairoids sends a POST request to the URL you configure. Here’s the payload structure:
{
  "event": "automation.action_triggered",
  "automation_id": "auto_01j4k8m2n3p5q6r7s8",
  "automation_name": "High-intent trial → notify sales",
  "triggered_at": "2024-09-01T14:32:05Z",
  "account": {
    "id": "acc_01j4k8m2n3p5q6r7",
    "name": "Acme Corp",
    "domain": "acmecorp.com"
  },
  "contact": {
    "id": "con_01j4k8m2n3p5q6r8",
    "email": "jane.doe@acmecorp.com",
    "first_name": "Jane",
    "last_name": "Doe"
  },
  "signal": {
    "id": "sig_01j4k8m2n3p5q6r7s8t9u0v1",
    "type": "product_trial_started",
    "source": "internal_app",
    "properties": {
      "plan": "pro_trial",
      "trial_ends_at": "2024-09-15T00:00:00Z"
    },
    "created_at": "2024-09-01T14:32:00Z"
  }
}

Verifying the HMAC-SHA256 signature

Every outgoing webhook includes an X-Stairoids-Signature header. Verify it to confirm the request genuinely came from Stairoids and hasn’t been tampered with. The signature is computed as:
HMAC-SHA256(webhook_secret, raw_request_body)
Your webhook secret is shown once when you configure the Webhook action in Stairoids. Store it securely. Here’s how to verify it:
const crypto = require('crypto');

function verifyStairoidsSignature(rawBody, receivedSignature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(rawBody, 'utf8')
    .digest('hex');

  const trusted = Buffer.from(`sha256=${expectedSignature}`, 'ascii');
  const received = Buffer.from(receivedSignature, 'ascii');

  // Use timingSafeEqual to prevent timing attacks
  return crypto.timingSafeEqual(trusted, received);
}

// In your Express route handler:
app.post('/webhook/stairoids', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-stairoids-signature'];
  const isValid = verifyStairoidsSignature(req.body, signature, process.env.STAIROIDS_WEBHOOK_SECRET);

  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }

  const payload = JSON.parse(req.body);
  // Handle payload...
  res.status(200).send('OK');
});

Send a signal from code

const axios = require('axios');

async function sendStairoidsSignal(signalData) {
  const response = await axios.post(
    'https://api.stairoids.com/v1/signals',
    signalData,
    {
      headers: {
        'Authorization': `Bearer ${process.env.STAIROIDS_API_KEY}`,
        'Content-Type': 'application/json',
      },
    }
  );
  return response.data;
}

// Usage
sendStairoidsSignal({
  type: 'demo_requested',
  source: 'website',
  account: { domain: 'acmecorp.com', name: 'Acme Corp' },
  contact: { email: 'jane.doe@acmecorp.com', first_name: 'Jane', last_name: 'Doe' },
  properties: { demo_type: 'product_tour', requested_at: new Date().toISOString() },
}).then(signal => console.log('Signal created:', signal.id));
If you’d rather not write code, use n8n or Make as a bridge between Stairoids and unsupported tools. Both platforms can send HTTP requests to POST /v1/signals and receive Stairoids outgoing webhooks using their built-in Webhook nodes — no custom code required. This lets you connect tools like Salesforce, Slack, Notion, Google Sheets, or virtually anything else with a few clicks.