Skip to main content

Overview

What you’ll build

A bidirectional integration enabling:
  • Automatic recording-to-opportunity matching
  • CRM context in Siro (customer names, deal amounts, outcomes)
  • Entity extraction data flowing back to your CRM

Time estimate

4-8 hours for a developer familiar with REST APIs

Prerequisites

  • API development experience
  • Admin access to your Siro workspace
  • Your system exposes appointment/opportunity data via API or database

Step 1: Get Your Siro API Credentials

Generate Your API Key

  1. Log into your Siro workspace as an admin
  2. Navigate to Person IconAPI Tokens
  3. Click Generate New API Token
  4. Store this securely - you’ll use it in all API requests

API Base URL

Most API calls use:
https://functions.siro.ai/api-externalApi/v1
Authentication: Include your API key in the header:
curl --request GET \
  --url 'https://functions.siro.ai/api-externalApi/v1/core/mobile-events?pageSize=100' \
  --header 'Authorization: Bearer <token>'
Documentation: Full API reference at docs.siro.ai

Step 2: Understand the Basics of the Data Model

Siro’s integration data model maps to standard CRM concepts:
Your SystemSiro EquivalentPurpose
Sales Rep / User in your CRMUserLink reps in CRM to reps in Siro
Customer / AccountAccountCustomer information
Opportunity / Deal / LeadOpportunitySales outcomes with dollar values
Appointment / MeetingEngagementScheduled interactions that get recorded
RecordingRecordingsSiro recording

Key Relationship

The critical link is: Recording ↔ Engagement ↔ Opportunity AND/OR Account When you sync an Engagement to Siro with appointment details (time, location, rep), Siro can automatically match recordings to that engagement and surface the linked Opportunity context.

Step 3: Sync Your Data to Siro

User linking happens automatically. When you sync engagements or opportunities, include your CRM’s user identifier with externalId, email, and name. Siro automatically maps to existing workspace users by email or name match. Manual override available in Settings → Integrations → User Mapping.

3.2 Sync Appointments (Engagements)

This is the core of the integration. Syncing engagements enables appointment lists for reps, automatic recording linking, and CRM context for AI features. Endpoint: PUT /v1/integrations/sync/engagementsFull docs Example request:
curl --request PUT \
  --url 'https://functions.siro.ai/api-externalApi/v1/integrations/sync/engagements' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '@-' <<EOF
{
  "externalId": "appt-456",
  "startTime": "2026-02-15T14:00:00Z",
  "endTime": "2026-02-15T15:00:00Z",
  "subject": "Smith Kitchen Remodel Consultation",
  "engagementType": {
    "activityType": "MEETING",
    "name": "meeting"
  },
  "engagementUsers": [
    {
      "externalId": "rep-123-from-your-crm",
      "email": "rep-123@kitchenremodel.com",
      "name": "John Sales"
    }
  ],
  "account": {
    "externalId": "account-789"
  },
  "opportunity": {
    "externalId": "opp-101"
  }
}
EOF
Payload notes:
  • activityType: Valid values are MEETING, CALL, APPOINTMENT, EMAIL, TEXT, EVENT
  • Only MEETING, APPOINTMENT, and EVENT appear in the Appointment List feature

3.3 Sync Opportunities

Adds deal context (amount, disposition, customer name) to recordings. Endpoint: PUT /v1/integrations/sync/opportunitiesFull docs Example request:
curl --request PUT \
  --url 'https://functions.siro.ai/api-externalApi/v1/integrations/sync/opportunities' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '@-' <<EOF
{
  "externalId": "opp-101",
  "name": "Smith Kitchen Remodel",
  "amount": 45000,
  "closedAt": "2026-03-01T00:00:00Z",
  "disposition": "WON",
  "account": {
    "externalId": "account-789"
  },
  "opportunityUsers": [
    {
      "externalId": "rep-123-from-your-crm",
      "email": "rep-123@kitchenremodel.com",
      "name": "John Sales"
    }
  ]
}
EOF

3.4 Sync Accounts

Adds customer context (name, address, contact info) to recordings. Account syncing happens automatically when you include the nested account object with an externalId in engagement or opportunity payloads. See the engagement example in 3.2 for the basic structure, or add optional fields like emailAddresses, phoneNumbers, and addresses as needed.

Step 4: Pull Data from Siro Back to Your System

Once recordings are created and linked, retrieve AI-generated insights. Siro supports two ways to receive this data:
  1. Real-time webhooks (recommended) — subscribe to events on your Siro workspace and receive HTTP callbacks the moment a recording is processed and linked to a CRM engagement. Covered in sections 4.1–4.3 below.
  2. Polling — periodically query the engagement endpoint to check for linked recordings, then pull enriched data from separate endpoints. See Alternative: Polling Flow.
Note: Most endpoints use your organization API token. Get Recording Details (section 4.3) and Get Entity Extractions (section 4.5) require OAuth authentication. Skip OAuth setup if you only need the polling flow for engagements and summaries.

OAuth Setup (Required for Recording Details & Entity Extractions)

1. Create an OAuth App

Endpoint: POST /v1/core/oauth/appsFull docs Provide appName, owner (user-id), and organizationId. Store the returned clientID and clientSecret securely.

2. Generate OAuth Access Tokens

Endpoint: POST /v1/core/oauth/apps/{clientId}/access-tokenFull docs Provide clientSecret, userId, and scope: "read". Use the returned accessToken for entity extractions. Tokens expire after 16 hours.

4.1 Subscribe to Webhook Events

Siro emits two event types that together signal a recording is fully ready for downstream processing:
Event typeFires when
integrations.recordingProcessedSiro finishes processing the recording (transcript, summary, entity extraction, etc.)
integrations.recordingLinkedSiro recording is definitively linked to a CRM record
These events fire independently and may arrive in either order — the recording may be linked before processing finishes, or vice versa. How to subscribe: Webhook subscriptions are managed from the Webhooks page in the Siro dashboard.
  1. As an org admin, open the Organization Admin Area from the top-right menu and select Webhooks. You’ll see the Endpoints list where all your configured webhooks are shown.
Webhooks endpoints list
  1. Click + Add Endpoint. Fill in your Endpoint URL (the HTTPS URL where you want to receive events), an optional Description, and select the events to subscribe to. Check both integrations.recordingLinked and integrations.recordingProcessed.
Add a new webhook endpoint
  1. After saving, you’ll see the endpoint detail page with your Signing Secret. Copy this secret — you’ll use it to verify that incoming webhook payloads are authentic.
Webhook endpoint detail with signing secret
You can test your endpoint before going live using the Testing tab on the endpoint detail page, or by using Webhook.site to inspect payloads without setting up a server.
Verifying webhook signatures Every webhook delivery includes three headers used for verification:
HeaderDescription
svix-idUnique message identifier
svix-timestampTimestamp in seconds since epoch
svix-signatureBase64-encoded signature(s), e.g. v1,<sig>
The recommended approach is to use the official Svix library, which handles signature construction and timestamp tolerance for you.
import { Webhook } from "svix"; // npm install svix

const secret = "whsec_YOUR_SIGNING_SECRET";

export default async function handler(req, res) {
  const payload = (await buffer(req)).toString(); // raw body
  const headers = req.headers;

  const wh = new Webhook(secret);
  try {
    wh.verify(payload, headers);
  } catch (err) {
    return res.status(400).json({});
  }

  // Signature valid — process the event
  res.json({});
}
You must use the raw request body when verifying. Parsing the JSON first and re-serializing it will break the signature.
Subscribe to both event types. Every delivery carries the current state of both flags regardless of which event triggered it, which is what makes the filtering rule in 4.2 work without any correlation logic on your side.

4.2 Handle Webhook Payloads

Both event types share the same payload shape:
{
  "recordingId": "rec-abc-def",
  "siroUserId": "siro-user-123",
  "recordingProcessed": true,
  "recordingLinked": true,
  "eventType": "integrations.recordingProcessed",
  "crm": {
    "integrationConnectionId": "conn-123",
    "users": [{ "id": "user-uuid", "externalId": "crm-user-123" }],
    "engagement": { "id": "eng-uuid", "externalId": "appt-456" },
    "opportunity": { "id": "opp-uuid", "externalId": "opp-101" },
    "account": { "id": "acct-uuid", "externalId": "account-789" }
  }
}
Key fields:
  • recordingProcessed / recordingLinked — current boolean state of each condition. Every payload reports both, regardless of which event was emitted.
  • crm.engagement.externalId — the appointment ID you originally synced (from 3.2).
  • crm.opportunity.externalId — the opportunity ID you originally synced (from 3.3).
Filtering rule: act only when both recordingProcessed and recordingLinked are true. Because every delivery reports current state for both conditions, the handler for whichever event fires last will naturally observe true / true — no correlation or state machine is needed. Example handler:
async function onSiroWebhook(payload) {
  if (!payload.recordingProcessed || !payload.recordingLinked) {
    // Not ready yet — the other event will arrive.
    return;
  }

  const { recordingId, crm } = payload;
  const engagementExternalId = crm?.engagement?.externalId;
  const opportunityExternalId = crm?.opportunity?.externalId;

  // Fetch enriched data — see 4.3
  const recording = await fetchRecordingDetails(recordingId);

  await yourCrm.attach({
    engagementExternalId,
    opportunityExternalId,
    summary: recording.summary,
    extractions: recording.entityExtractions,
  });
}
Idempotency: because the “both true” condition can be observed twice (once per event), dedupe by recordingId if your downstream side-effects aren’t idempotent.

4.3 Get Recording Details (Summary + Entity Extractions)

Endpoint: GET /v1/core/recordings/{recordingId} Base URL: https://api.siro.ai Note: This base URL is different from the main external API (https://functions.siro.ai/api-externalApi/v1). It matches the base used by the Entity Extractions endpoint (4.5). Authentication: Use OAuth access token (header: x-siro-auth-token) — see the OAuth Setup section above. Query parameters:
ParamTypePurpose
showSummarybooleanInclude the concatenated LLM summary in the response
showEntityExtractionsbooleanInclude per-definition entity extractions with CRM mappings
Both default to false. Example request:
curl --request GET \
  --url 'https://api.siro.ai/v1/core/recordings/rec-abc-def?showSummary=true&showEntityExtractions=true' \
  --header 'x-siro-auth-token: YOUR_OAUTH_ACCESS_TOKEN'
Response (relevant fields):
{
  "data": {
    "id": "rec-abc-def",
    "organizationId": "org-789",
    "userId": "user-123",

    "summary": "Overview:\nThe rep walked the customer through financing options.\n\nNext Steps:\nSend a written proposal by Friday.",

    "entityExtractions": [
      {
        "id": "extraction_001",
        "recordingId": "rec-abc-def",
        "siroEntityDefinitionId": "def-uuid",
        "siroEntityDefinitionName": "Budget",
        "status": "SUCCESS",
        "extraction": [
          {
            "name": "Budget",
            "value": "$40,000 - $50,000",
            "mappings": [
              { "crmModelName": "Opportunity", "crmFieldName": "Budget__c" }
            ]
          }
        ]
      }
    ]
  }
}
Use case: in a single round-trip, pull both the conversation summary and any extracted custom fields ready to write back to your CRM.

Alternative: Polling Flow

If webhooks aren’t an option for your environment, use the engagement endpoint to poll for linked recordings and pull enriched data from the endpoints below. This flow uses an org API token for everything except entity extractions (4.5), which still requires OAuth.

4.4 Get Linked Recording for an Engagement

Endpoint: GET /v1/integrations/engagements/{id}Full docs Response includes:
{
  "id": "eng-123",
  "externalId": "appt-456",
  "recordingId": "rec-abc-def",
  "engagementType": "appointment",
  "opportunityId": "opp-101",
  "accountId": "account-789"
}
Use the recordingId to fetch detailed data.

4.5 Get Entity Extractions (CRM Autofill Data)

Endpoint: GET /v1/core/entities/extractions/{recordingId}Full docs Base URL: https://api.siro.ai Note: This base URL is different from other API endpoints. Authentication: Use OAuth access token (header: x-siro-auth-token) Response example:
{
  "data": [
    {
      "id": "extraction_001",
      "recordingId": "rec-abc-def",
      "extraction": [
        {
          "name": "Budget",
          "value": "$40,000 - $50,000"
        },
        {
          "name": "Timeline",
          "value": "Spring 2026"
        },
        {
          "name": "Decision Maker",
          "value": "Both homeowners present, wife is primary"
        },
        {
          "name": "Objections",
          "value": "Concerned about project timeline due to summer vacation plans"
        }
      ],
      "createdAt": "2026-01-28T00:00:00Z",
      "updatedAt": "2026-01-28T00:00:00Z"
    }
  ]
}
Use case: Write extracted fields back to your CRM to auto-populate data from conversations.

4.6 Get Recording Summaries

Endpoint: GET /v1/core/recordings/{recordingId}/summaries Response:
{
  "data": [
    {
      "id": "summary-001",
      "name": "AI Summary",
      "content": "Summary text here..."
    }
  ]
}
Use case: Write summaries as CRM notes to create an activity trail.

Auto Start/Stop via Deep Linking (Optional)

Start Siro recordings directly from your mobile app: URL format:
siro://record?appointmentId={external-id}&title={customer-name}&opportunityId={opp-external-id}
Example:
siro://record?appointmentId=appt-456&title=Smith Kitchen Remodel&opportunityId=opp-101
Siro will use the appointmentId to link the recording to the engagement and opportunityId to link the associated opportunity immediately.

Next Steps

  • Test it: Sync a test appointment, record a conversation at that time, and verify CRM context appears
  • Automate syncs: Use real-time webhooks (recommended) or batch jobs every 10 minutes
  • Custom fields: Work with your CSM to configure custom entity extraction fields
  • Troubleshoot: If recordings aren’t linking, check Settings → Users to verify email mappings
  • Train your team: Show reps how recordings link to CRM records

Getting Help

Technical questions: Email your Customer Success Manager or reach out to customersuccess@siro.ai API issues: Include your request details (method, endpoint, payload) and organization ID when reaching out.