Submit an end-user message without waiting for Zeus to generate a reply. This
endpoint supports only account-owned agent channels of type api and must be
called from your server.
Send a message
POST https://api.openfi.tech/v1/messages
Content-Type: application/json
x-api-key: YOUR_API_KEY
Idempotency-Key: CUSTOMER_GENERATED_KEY
Zeus persists the incoming message and its processing work before returning
202 Accepted. Processing continues asynchronously.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
agentChannelId | UUID | Yes | The account-owned API agent channel handling the conversation. |
contactChannelExternalId | string | Yes | Your non-empty, stable identifier for the end user or chat session. |
content | string | Yes | The end-user message. It must contain 1–255 characters and cannot be blank. |
The API key determines the account. The pair of agentChannelId and
contactChannelExternalId identifies the conversation thread within that
account.
Idempotency
Idempotency-Key is required. Generate one key for each logical end-user
message, store it with that message, and reuse it when retrying the same
request. A UUID is a suitable key.
- The key must contain between 1 and 255 characters and cannot be blank.
- Keys are scoped to the API account and this endpoint.
- Request identity consists of
agentChannelId,contactChannelExternalId, andcontentafter request validation. - Reusing a key with the same values for those three fields returns the
original
202response and does not create another message or processing job. - Changing any of those three values while reusing the key returns
409 Conflict. - Keys and their original acceptance responses remain replayable for at least 24 hours.
Example request
Load the API key into ZEUS_API_KEY from your secret manager or a secure
shell prompt.
curl --request POST 'https://api.openfi.tech/v1/messages' \
--header 'Content-Type: application/json' \
--header "x-api-key: ${ZEUS_API_KEY}" \
--header 'Idempotency-Key: 67b3d02d-58cc-4ce0-b852-70edecb55cb3' \
--data '{
"agentChannelId": "YOUR_API_AGENT_CHANNEL_ID",
"contactChannelExternalId": "customer-user-123",
"content": "I would like to book an appointment."
}'
Accepted response
HTTP/1.1 202 Accepted
{
"status": "accepted",
"requestId": "39703f17-908e-4d67-b44d-b41d2958d21f",
"intentId": "09c84d67-6b6b-47c4-9d9b-d63f74920ec3",
"messageId": "9f1d651f-b297-4562-a001-190a876bdd80"
}
messageId identifies the persisted incoming message. requestId can be
used when tracing the accepted API request. A 202 response does not mean
that an outgoing message has been generated, and an accepted incoming
message does not always produce a reply.
Receive outgoing messages through webhooks. The
outgoing event is not a per-request completion event and does not include
requestId or a guaranteed one-to-one reply correlation.
Thread initialization
You can call this endpoint with or without first calling Create an intent.
If the contact, API contact channel, or applicable intent is missing, Zeus
creates it using source api and empty contact and intent attributes. The
first incoming message is processed as the answer to the initial flow
question.
If a thread already exists, Zeus selects the latest non-expired intent for
the resolved contact and agent. Call POST /v1/intents first when you need
seeded attributes or an initial outgoing message.
Concurrent messages
You may submit more messages while earlier ones are still being processed. Distinct idempotency keys represent distinct requests, and every valid request is accepted independently. Parallel first messages for the same channel pair share one contact, API contact channel, and applicable intent.
Current conversation behavior can intentionally produce no outgoing reply, including when a newer message supersedes processing or a human manages the conversation. Do not assume one outgoing webhook for every accepted message.
Errors and retries
| Status | Meaning | Action |
|---|---|---|
400 Bad Request | The body or Idempotency-Key is missing or invalid. | Correct the request before retrying. |
401 Unauthorized | The x-api-key header is missing or invalid. | Use a valid server-side API key. |
404 Not Found | The agent channel is missing, belongs to another account, or is not an API channel. | Check the configured API agentChannelId. |
409 Conflict | The Idempotency-Key was already used with a different request. | Do not retry with that key. Investigate the conflicting request. |
429 Too Many Requests | The account exceeded 1,200 message requests in one hour. | Retry the same request and key after Retry-After. |
500 Internal Server Error | The message was not confirmed as accepted. | Retry the same request with the same Idempotency-Key. |
Treat a network timeout like an unknown outcome: retry the identical body with the same idempotency key.