Skip to content
Conversation API

Sessions & Messages

Create AI chat sessions, send messages, submit forms, and receive responses via REST or callbacks.

On this page

Conversations API#

The Conversations API lets you create and manage AI chat sessions programmatically. Use it to integrate Gydr-powered chat into social media platforms, custom chat interfaces, mobile apps, messaging services, and any channel beyond the widget SDK.

Endpoints#

MethodPath
POST/widgets/{widgetId}/conversations
POST/widgets/{widgetId}/conversations/{sessionId}/messages
POST/widgets/{widgetId}/conversations/{sessionId}/end
POST/widgets/{widgetId}/conversations/{sessionId}/rate
GET/widgets/{widgetId}/conversations/{sessionId}
GET/widgets/{widgetId}/conversations/{sessionId}/messages
POST/widgets/{widgetId}/conversations/{sessionId}/form-submissions

Session Lifecycle#

A conversation follows a simple lifecycle:

  1. Create Session — initialize a new chat session for a visitor
  2. Send Messages — exchange messages back and forth with the AI
  3. End Session — resolve the session when the conversation is complete
  4. Rate Session (optional) — collect visitor feedback after the session ends

You can retrieve session details and message history at any point using the GET endpoints.

New: the assistant response shape can now be configured per API key — Markdown (default), Plain text, Facebook Messenger, or WhatsApp Business. See Response Formats for the full reference, code samples, and channel mapping tables.

Response Modes#

The Send Message endpoint supports two response types:

TypeBehaviorBest For
syncSynchronous. Waits for the AI response before returning (~25s timeout).Simple queries, real-time chat UIs
callbackAsynchronous. Returns 202 immediately, delivers the AI response to your callback URL.Complex multi-tool queries, social media integrations

Create Session#

Initializes a new chat session for a given widget. You can optionally provide a custom session ID, visitor context, and a preferred language.

curl -X POST https://api.infinichat.dev/widgets/{widgetId}/conversations \
  -H "X-API-Key: api_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "visitorId": "user_12345",
    "visitorContext": {
      "name": "John",
      "email": "john@example.com"
    },
    "language": "en",
    "timezone": "Asia/Kuala_Lumpur"
  }'

Response (201 Created for a new session):

{
  "data": {
    "sessionId": "sess_dBLPP9tYcVKrzrxC5_gTR",
    "widgetId": "6751a3e...",
    "visitorId": "user_12345",
    "status": "active",
    "createdAt": "2026-03-23T10:00:00.000Z",
    "resumed": false
  },
  "meta": { "creditsConsumed": 1 }
}

If you supply a sessionId that already exists and is still active, the API returns 200 with resumed: true instead of 201 — no new session is created and the existing conversation history is preserved.

Create Session Fields#

FieldTypeRequiredDescription
visitorIdstringYesYour unique identifier for the visitor (1-128 chars, alphanumeric + _-.:@)
sessionIdstringNoCustom session ID. Server generates one if omitted.
visitorContextobjectNoVisitor details: name, email, phone, company
languagestringNoBCP 47 language code (e.g., "en", "ms", "zh"). AI responds in this language initially.
timezonestringNoIANA timezone (e.g., "Asia/Kuala_Lumpur", "America/New_York"). Used for time-aware responses.

Send Message (Sync)#

Sends a message to the AI and waits for the response. The default response type is sync.

curl -X POST https://api.infinichat.dev/widgets/{widgetId}/conversations/{sessionId}/messages \
  -H "X-API-Key: api_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "What products do you have under $50?",
    "response_type": "sync"
  }'

Response:

{
  "data": {
    "messageId": "msg_abc123",
    "content": "Here are some products under $50...",
    "products": [
      { "id": "prod_1", "name": "Wireless Earbuds", "price": 29.99 }
    ],
    "actions": [],
    "sessionEnded": false,
    "credits": { "chat": 8, "retrieval": 2, "orchestration": 1, "embedding": 0, "rerank": 1, "plugin": 1, "crawler": 0 },
    "usage": { "inputTokens": 1234, "outputTokens": 567 }
  },
  "meta": { "creditsConsumed": 15 }
}

Send Message (Callback)#

For longer-running queries, use callback mode. The API returns immediately with a 202 status and delivers the AI response to your configured callback URL when processing completes.

curl -X POST https://api.infinichat.dev/widgets/{widgetId}/conversations/{sessionId}/messages \
  -H "X-API-Key: api_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Compare all your laptop models by price and features",
    "response_type": "callback"
  }'

Immediate response (202 Accepted):

{
  "data": {
    "messageId": null,
    "status": "processing"
  },
  "meta": { "creditsConsumed": 0 }
}

The messageId is null in the immediate response because the message has not been processed yet. The actual messageId is included in the callback payload delivered to your callback URL.

Send Message Fields#

FieldTypeRequiredDescription
contentstringYesThe visitor's message (1–4000 chars)
response_typestringNosync (default) or callback
visitorContextobjectNoVisitor identity fields (name, email, phone, company) to upsert onto the visitor record mid-conversation. Useful when identity is captured after session creation.
timezonestringNoPer-turn IANA timezone override (e.g. "Asia/Kuala_Lumpur"). Falls back to the session's stored timezone when omitted. Used for time-aware responses and Dynamic Form date/time answers.

Callback Payload#

When using callback mode, the AI response is delivered to your callback URL as a POST request with the following payload:

{
  "event": "message.completed",
  "messageId": "msg_abc123",
  "sessionId": "sess_abc123",
  "widgetId": "6751a3e...",
  "data": {
    "content": "Here are some products...",
    "products": [
      { "id": "prod_1", "name": "Wireless Earbuds", "price": 29.99 }
    ],
    "actions": [],
    "sessionEnded": false,
    "credits": { "chat": 10, "retrieval": 2, "orchestration": 1, "embedding": 0, "rerank": 1, "plugin": 2, "crawler": 0 },
    "usage": { "inputTokens": 1234, "outputTokens": 567 }
  }
}

The credits object always carries the same seven numeric keys — see Response Formats → The credits Field.

Breaking change (1.31.0)

The credits.api field was renamed to credits.plugin, and the retrieval, orchestration, and crawler buckets were added. Update any code that reads credits.api to read credits.plugin.

Callback Signature Verification#

Every callback delivery includes three headers:

  • X-Gydr-Signature — HMAC-SHA256 hex digest for verifying authenticity
  • X-Gydr-Timestamp — Unix timestamp of the delivery
  • X-Gydr-Event — event type: message.completed or message.failed

The signature is computed as HMAC-SHA256(callbackSecret, "{timestamp}.{rawBody}"). Verify it using your callback secret (provided when you create the API key with a callback URL):

import crypto from "crypto"

function verifyCallbackSignature(rawBody, headers, callbackSecret) {
  const timestamp = headers["x-gydr-timestamp"]
  const signature = headers["x-gydr-signature"]

  const expected = crypto
    .createHmac("sha256", callbackSecret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex")

  const isValid = crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  )

  // Optional: reject if timestamp is older than 5 minutes
  const age = Math.abs(Date.now() / 1000 - parseInt(timestamp))
  if (age > 300) return false

  return isValid
}

If callback delivery fails, the system retries up to 3 times with backoff intervals of 0, 1, and 5 seconds. Failed deliveries do not result in data loss — messages are stored in the database and can be retrieved via the Get Messages endpoint.

Callback URL setup

Configure a callback URL when creating your API key in Console → Settings → Developer. The callback secret is shown once at creation time. Callback mode returns a 400 error if no callback URL is configured on the API key.

Automatic session resolution

When the AI detects the conversation has concluded naturally (e.g., the visitor says "thank you"), sessionEnded is returned as true and the session is automatically resolved. You do not need to call the End Session endpoint in this case.

Submit Form#

When the AI surfaces a Dynamic Form in a response (forms array non-empty), visitor answers must be submitted via this endpoint — not as a plain message. A rejected submission (wrong formId, invalid answer, or no pending form) returns 400 before any billing or agent run. Accepted submissions run the answer turn and are billed exactly like a send-message turn.

curl -X POST https://api.infinichat.dev/widgets/{widgetId}/conversations/{sessionId}/form-submissions \
  -H "X-API-Key: api_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "formId": "frm_abc123",
    "answers": {
      "q1": "John Smith",
      "q2": "john@example.com"
    }
  }'

Response (same shape as send-message):

{
  "data": {
    "messageId": "msg_abc123",
    "content": "Thanks, John! We'll be in touch at john@example.com shortly.",
    "products": [],
    "actions": [],
    "sessionEnded": false,
    "credits": { "chat": 6, "retrieval": 0, "orchestration": 1, "embedding": 0, "rerank": 0, "plugin": 0, "crawler": 0 },
    "usage": { "inputTokens": 890, "outputTokens": 42 }
  },
  "meta": { "creditsConsumed": 9 }
}

End Session#

Resolves an active session. After ending, no more messages can be sent.

curl -X POST https://api.infinichat.dev/widgets/{widgetId}/conversations/{sessionId}/end \
  -H "X-API-Key: api_your_api_key"

Response:

{
  "data": {
    "sessionId": "sess_abc123",
    "status": "resolved",
    "resolvedAt": "2026-03-23T10:15:00.000Z"
  },
  "meta": { "creditsConsumed": 1 }
}

Rate Session#

Submits a satisfaction rating for a resolved or expired session. Only positive and negative values are accepted.

curl -X POST https://api.infinichat.dev/widgets/{widgetId}/conversations/{sessionId}/rate \
  -H "X-API-Key: api_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "rating": "positive" }'

Response:

{
  "data": {
    "sessionId": "sess_abc123",
    "rating": "positive"
  },
  "meta": { "creditsConsumed": 1 }
}

Get Session#

Retrieves the current state and metadata of a session.

curl https://api.infinichat.dev/widgets/{widgetId}/conversations/{sessionId} \
  -H "X-API-Key: api_your_api_key"

Response:

{
  "data": {
    "sessionId": "sess_abc123",
    "widgetId": "6751a3e...",
    "visitorId": "user_12345",
    "status": "active",
    "messageCount": 5,
    "rating": null,
    "createdAt": "2026-03-23T10:00:00.000Z",
    "resolvedAt": null
  },
  "meta": { "creditsConsumed": 1 }
}

Get Messages#

Retrieves the message history for a session. Supports cursor-based pagination for sessions with many messages.

curl "https://api.infinichat.dev/widgets/{widgetId}/conversations/{sessionId}/messages?limit=20" \
  -H "X-API-Key: api_your_api_key"

# Next page (use cursor from previous response)
curl "https://api.infinichat.dev/widgets/{widgetId}/conversations/{sessionId}/messages?limit=20&cursor=eyJ0..." \
  -H "X-API-Key: api_your_api_key"

Response:

{
  "data": [
    {
      "messageId": "msg_001",
      "role": "user",
      "content": "What products do you have under $50?",
      "createdAt": "2026-03-23T10:01:00.000Z"
    },
    {
      "messageId": "msg_002",
      "role": "assistant",
      "content": "Here are some products under $50...",
      "products": [
        { "id": "prod_1", "name": "Wireless Earbuds", "price": 29.99 }
      ],
      "createdAt": "2026-03-23T10:01:05.000Z"
    }
  ],
  "pagination": { "cursor": "eyJ0...", "hasMore": true },
  "meta": { "creditsConsumed": 1 }
}

Every response carries meta.creditsConsumed so you can attribute metered usage per request. What each operation costs is documented in How Credits Work.

Custom Session & Visitor IDs#

You can provide your own identifiers to correlate conversations with your application data:

  • visitorId — map to your user database (e.g., customer ID, social media user ID). The same visitor ID can create multiple sessions across different widgets.
  • sessionId — use your own identifier for tracking (e.g., support ticket ID, thread ID). Must be unique per widget. If omitted, the server generates a sess_ prefixed ID.

Error Scenarios#

StatusCauseResolution
400Callback URL not configured for this API key (response_type: "callback" with no callback URL set)Set a callback URL in Console → Settings → Developer when creating your API key
402Account balance exhausted or payment overdueResolve the account balance in Console
404Session or widget not foundVerify the widget ID and session ID are correct
409Session ID already used for a resolved or expired sessionUse a new session ID or omit it to auto-generate

See the Error Handling page for the full error response format and general error codes.

We use cookies to run and improve Gydr.

Read our Cookie Policy