On this page
- Conversations API
- Endpoints
- Session Lifecycle
- Response Modes
- Create Session
- Create Session Fields
- Send Message (Sync)
- Send Message (Callback)
- Send Message Fields
- Callback Payload
- Callback Signature Verification
- Submit Form
- End Session
- Rate Session
- Get Session
- Get Messages
- Custom Session & Visitor IDs
- Error Scenarios
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#
| Method | Path |
|---|---|
| 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:
- Create Session — initialize a new chat session for a visitor
- Send Messages — exchange messages back and forth with the AI
- End Session — resolve the session when the conversation is complete
- 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.
Response Modes#
The Send Message endpoint supports two response types:
| Type | Behavior | Best For |
|---|---|---|
sync | Synchronous. Waits for the AI response before returning (~25s timeout). | Simple queries, real-time chat UIs |
callback | Asynchronous. 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#
| Field | Type | Required | Description |
|---|---|---|---|
visitorId | string | Yes | Your unique identifier for the visitor (1-128 chars, alphanumeric + _-.:@) |
sessionId | string | No | Custom session ID. Server generates one if omitted. |
visitorContext | object | No | Visitor details: name, email, phone, company |
language | string | No | BCP 47 language code (e.g., "en", "ms", "zh"). AI responds in this language initially. |
timezone | string | No | IANA 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#
| Field | Type | Required | Description |
|---|---|---|---|
content | string | Yes | The visitor's message (1–4000 chars) |
response_type | string | No | sync (default) or callback |
visitorContext | object | No | Visitor identity fields (name, email, phone, company) to upsert onto the visitor record mid-conversation. Useful when identity is captured after session creation. |
timezone | string | No | Per-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 authenticityX-Gydr-Timestamp— Unix timestamp of the deliveryX-Gydr-Event— event type:message.completedormessage.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#
| Status | Cause | Resolution |
|---|---|---|
| 400 | Callback 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 |
| 402 | Account balance exhausted or payment overdue | Resolve the account balance in Console |
| 404 | Session or widget not found | Verify the widget ID and session ID are correct |
| 409 | Session ID already used for a resolved or expired session | Use 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.