How to create a helpdesk integration

Log Consio calls as helpdesk tickets and sync SMS conversations with the Public API and webhooks.

A helpdesk integration keeps your ticketing system in sync with Consio: each completed call becomes a ticket, later logging and summaries land on that ticket, and SMS conversations flow both ways.

This guide uses the Public API and webhooks. Identifiers in every payload are opaque resource IDs (rid), never numeric database IDs.

What you will build

DirectionConsio event or APIHelpdesk action
Call endscall.completedCreate (or upsert) a ticket keyed by call.rid
Agent logs the callcall.loggedAdd disposition and notes on that ticket
Consio summarizes the callcall.summarizedAdd the summary and next steps on that ticket
Customer texts inmessage.received, then message_media.processedOpen or append a conversation
Agent replies in the helpdeskCreate and send an SMSSend the reply through Consio
Consio delivers or fails the SMSmessage.delivered / message.failedUpdate delivery status on the conversation

Store three mappings locally:

  • event_id so retries are ignored
  • call.rid to the helpdesk ticket
  • customer_rid to the SMS conversation

Authenticate

Generate an API key under Settings > API Keys and send it on every request. See Authentication.

Authorization: Bearer YOUR_API_KEY

Production requests go to https://api.consio.ai/v1/{workspace_slug}/.... Replace {workspace_slug} with the workspace slug from the Consio URL.

Register a webhook

Create an HTTPS endpoint, then subscribe it with Create webhook (or Settings > Webhooks). Save secret from the create response; Consio shows it only once. Use it to verify signatures.

{
  "url": "https://example.com/consio/webhooks",
  "description": "Helpdesk sync",
  "events": [
    "call.completed",
    "call.logged",
    "call.summarized",
    "message.received",
    "message.delivered",
    "message.failed",
    "message_media.processed"
  ]
}

Consio POSTs JSON to your URL with User-Agent: Consio-Webhooks/1.0 and X-Consio-Signature. Return HTTP 2xx within 5 seconds. Delivery is at-least-once: retries reuse the same event_id. There is no ordering guarantee across events.

ℹ️

Upsert by call.rid or message.rid. call.logged or call.summarized can arrive before call.completed. Queue the later note until the ticket exists, or create the ticket from whichever event arrives first.

Log calls into the helpdesk

A call produces up to three webhook events. Handle each as a step on one ticket.

sequenceDiagram
  participant Consio
  participant Your API
  participant Helpdesk
  Consio->>Your API: call.completed
  Your API->>Helpdesk: Create ticket keyed by call.rid
  Your API->>Consio: POST /calls/{call_rid}/links
  Consio->>Your API: call.logged
  Your API->>Helpdesk: Add disposition and notes
  Consio->>Your API: call.summarized
  Your API->>Helpdesk: Add summary and next steps

call.completed: open the ticket

Fires when the call reaches a terminal status. The payload is a call object. status is often completed; missed or failed calls use other terminal values such as not_answered or failed. disposition is already set when Consio auto-logs the outcome (for example a missed inbound).

{
  "event_id": "6f1a2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
  "event": "call.completed",
  "workspace_rid": "…",
  "call": {
    "rid": "…",
    "status": "completed",
    "trigger_type": "inbound",
    "customer_rid": "…",
    "phone_number_rid": "…",
    "user_rid": null,
    "ai_agent_rid": "…",
    "campaign_rid": null,
    "customer_phone_number": "+15551234567",
    "duration": 128,
    "disposition": null,
    "notes": null,
    "logged_at": null,
    "created_at": "2026-07-24T12:00:00Z",
    "updated_at": "2026-07-24T12:02:08Z"
  }
}

Create a ticket keyed by call.rid:

  • Subject such as Call with +15551234567 on Consio
  • Customer phone from customer_phone_number
  • Direction from trigger_type (inbound, outbound_click, outbound_power)
  • Duration in seconds
  • Agent from user_rid (human) or ai_agent_rid (AI)

If the ticket already exists for that call.rid, skip creation.

Then attach the ticket URL back onto the Consio call with Attach a link to a call. The call rid goes in the path. Posting the same URL twice returns the existing link.

POST /v1/{workspace_slug}/calls/{call_rid}/links
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "url": "https://helpdesk.example.com/tickets/12345",
  "title": "Call with +15551234567 on Consio",
  "external_uid": "12345"
}

Optional: fetch a call transcript and add it as a note. Utterances include speaker (customer, agent, ai) and transcript. For a historical backfill, list completed calls with Get completed calls.

call.logged: add disposition and notes

Fires when an agent submits a disposition. The payload is the same call object, with disposition and logged_at set.

{
  "event_id": "9c8b7a65-4321-4fed-9876-0123456789ab",
  "event": "call.logged",
  "workspace_rid": "…",
  "call": {
    "rid": "…",
    "status": "completed",
    "trigger_type": "outbound_click",
    "customer_rid": "…",
    "phone_number_rid": "…",
    "user_rid": "…",
    "ai_agent_rid": null,
    "campaign_rid": null,
    "customer_phone_number": "+15551234567",
    "duration": 128,
    "disposition": "closed_sale",
    "notes": "Customer confirmed the reorder",
    "logged_at": "2026-07-24T12:04:11Z",
    "created_at": "2026-07-24T12:00:00Z",
    "updated_at": "2026-07-24T12:04:11Z"
  }
}

Look up the ticket by call.rid and post an internal note:

Call was logged on Consio.

Disposition: closed_sale

Notes: Customer confirmed the reorder

Common dispositions include closed_sale, follow_up_needed, issue_resolved, no_answer, voicemail_left, not_interested, and other. Treat the value as an opaque string and display it as-is.

call.summarized: add the summary

Fires after Consio generates the summary. The payload is call_summary, not call. Join to your ticket with call_summary.call_rid.

{
  "event_id": "1b2c3d4e-5f60-4718-9a2b-3c4d5e6f7081",
  "event": "call.summarized",
  "workspace_rid": "…",
  "call_summary": {
    "rid": "…",
    "call_rid": "…",
    "summary": ["Customer asked about a delayed order"],
    "next_steps": ["Send the tracking link"],
    "generated_at": "2026-07-24T12:05:00Z"
  }
}

Post both lists as a note:

Call was summarized on Consio.

Summary:
- Customer asked about a delayed order

Next steps:
- Send the tracking link

Send and receive SMS

Treat SMS as a conversation per customer_rid. Inbound messages and outbound replies share that key.

sequenceDiagram
  participant Customer
  participant Consio
  participant Your API
  participant Helpdesk
  Customer->>Consio: Inbound SMS / MMS
  Consio->>Your API: message.received
  Your API->>Helpdesk: Open or append conversation
  Consio->>Your API: message_media.processed (per attachment)
  Your API->>Helpdesk: Attach downloaded media
  Helpdesk->>Your API: Agent reply
  Your API->>Consio: POST /messages
  Consio->>Customer: Outbound SMS
  Consio->>Your API: message.delivered or message.failed

Receive an inbound SMS

message.received fires after Consio persists the inbound message. trigger_type is INBOUND. Match the customer with customer_rid or customer_phone_number.

{
  "event_id": "550e8400-e29b-41d4-a716-446655440000",
  "event": "message.received",
  "workspace_rid": "…",
  "message": {
    "rid": "…",
    "type": "SMS",
    "content": "Where is my order?",
    "trigger_type": "INBOUND",
    "customer_rid": "…",
    "phone_number_rid": "…",
    "user_rid": null,
    "ai_agent_rid": null,
    "customer_phone_number": "+15551234567",
    "external_status": null,
    "sent_at": null,
    "delivered_at": null,
    "failed_at": null,
    "created_at": "2026-07-24T12:00:00Z",
    "updated_at": "2026-07-24T12:00:00Z",
    "medias": []
  }
}

Open a conversation if none exists for customer_rid, otherwise append a customer message. Use message.rid for idempotency.

Inbound attachments are stored after this event, so medias is usually []. Subscribe to message_media.processed for the files.

Receive MMS attachments

Each inbound attachment fires its own message_media.processed event after Consio stores the file. Join it to the SMS with media.message_rid. Download media.url before url_valid_until (60 minutes). After expiry, Get message details returns a fresh signed URL on each media item.

{
  "event_id": "3e4f5061-7283-49a4-b5c6-d7e8f90a1b2c",
  "event": "message_media.processed",
  "workspace_rid": "…",
  "media": {
    "rid": "…",
    "message_rid": "…",
    "content_type": "image/png",
    "size_in_kb": 42.0,
    "extension": "png",
    "url": "https://storage.googleapis.com/…",
    "url_valid_until": "2026-07-24T13:00:00Z"
  }
}

Copy the bytes into your helpdesk while the URL is valid. Do not persist the signed URL as a long-lived attachment link.

Send an outbound SMS from the helpdesk

When an agent replies, call Create and send an SMS. to_phone_number must be E.164. Omit from_phone_number to use the workspace default SMS number, or set it to a specific Consio number. Set user_rid to attribute the message to the matching Consio user; otherwise Consio attributes it to the user who created the API key.

POST /v1/{workspace_slug}/messages
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "content": "Your order ships tomorrow.",
  "to_phone_number": "+15551234567",
  "user_rid": "…"
}

The response includes rid, customer, and timestamps. Store rid on the helpdesk message so later message.delivered / message.failed events can update it.

This endpoint sends text SMS. It does not accept attachments.

Useful errors:

HTTPtypeMeaning
429MESSAGE_ALREADY_IN_PROGRESSThe same body is already sending to this customer; wait and retry
409AMBIGUOUS_CUSTOMERSeveral customers share that phone number
400FROM_PHONE_NUMBER_NOT_SMS_ENABLED / NO_SMS_ENABLED_PHONE_NUMBERThe selected (or default) Consio number cannot send SMS
400PHONE_NUMBER_MERGE_BLOCKLISTEDThat destination cannot be written

Track delivery

message.delivered and message.failed reuse the message payload. Match on message.rid. trigger_type is OUTBOUND_MANUAL or OUTBOUND_AI. On failure, failed_at is set; Get message details also returns error_message.

Outbound medias lists attachments that were already stored when the event was queued.

Implementation notes

Deduplicate. Ignore a delivery whose event_id you already processed.

Key tickets by Consio IDs. call.rid for call tickets, customer_rid for SMS conversations, message.rid for individual SMS rows.

Verify every webhook. Read the raw body, check X-Consio-Signature, and reject timestamps older than 300 seconds. See Verifying signatures.

Stay under the delivery budget. Return 2xx quickly and do helpdesk work asynchronously. Consio retries on 5xx, 408, 425, and 429 (honoring Retry-After, capped at 10 minutes).

HTTPS only. Webhook URLs must be absolute https. Maximum 20 endpoints per workspace.


Did this page help you?