Skip to content

Developer docs

Talking to an agent

One request sends a customer message to an agent. The agent may look things up with its tools before it answers.

Send a message

HTTP
Request (HTTP)POST https://api.safecoin.online/v1/agents/{agentId}/messages

Request body
FieldRequiredMeaning
messageYesThe customer’s text, 1 to 20,000 characters.
conversationIdNoThe id from an earlier reply, to continue that conversation. Leave it out to start a new one.

agentId is the agent’s catalogue id: support_agent, sales_lead_agent or operations_agent. No other fields are accepted; unknown fields are rejected with invalid_request.

Continue a conversation (curl)curl https://api.safecoin.online/v1/agents/support_agent/messages \
  -H "Authorization: Bearer $HAVEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "It is order 1042", "conversationId": "7d0f6c1e-5b0a-4a7e-8f55-0c3a6a0b9d11"}'

The response

Response fields
FieldMeaning
conversationIdSend this back to continue the conversation.
replyThe agent’s answer, as plain text.
pendingApprovalsActions the agent wants to take that wait for a person to approve: [{ approvalId, tool }]. See approvals.
toolCallsWhat the agent did while answering: [{ name, status }].
stopReasonWhy the agent stopped, for example end_turn when it finished its answer.
iterationsHow many model calls the answer took (at most 8).
usageYour message allowance: used, cap, remaining, periodEnd and warning (set once you pass 80%).

Each message you send uses one message from your plan, however many tools the agent uses to answer it. When you pass 80% of your allowance the response also carries the header X-Haven-Usage-Warning.

Stream the answer live

For a typing effect use the streaming route. It takes the same body and sends text/event-stream events as the agent works:

HTTP
Streaming route (HTTP)POST https://api.safecoin.online/v1/agents/{agentId}/chat

Stream events
EventData
conversationThe conversation id, sent first.
textA piece of the reply. Join the pieces in order.
toolThe agent used a tool: name, status and, for actions that wait for approval, approvalId.
doneThe finished result, with the same fields as the JSON response.
errorerror and message. The stream ends.
Node.js
Read the stream in Node.js (Node.js)const res = await fetch('https://api.safecoin.online/v1/agents/support_agent/chat', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.HAVEN_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ message: 'Hello' }),
});
if (!res.ok) throw new Error((await res.json()).message);

const decoder = new TextDecoder();
for await (const chunk of res.body) {
  process.stdout.write(decoder.decode(chunk, { stream: true })); // raw "event: …" / "data: …" lines
}

The streaming route does not take an Idempotency-Key. If you need safe retries, use the JSON route.

When an agent cannot answer

Before any model is called, Haven checks that the agent is allowed to answer. If not, you get an error and no message is used:

Why a message is refused
Status and codeMeaning and what to do
402 agent_pausedThe subscription is not active, ran out of messages, or is on hold. Read reason and message; renew or upgrade in the dashboard.
409 agent_not_configuredFinish the agent’s setup in the dashboard first.
404 agent_not_foundThe agent id is wrong.
409 conversation_busyThe conversation is still answering your previous message. Wait for it, then send the next one.
409 conversation_fullThe conversation has grown too long. Start a new one (leave out conversationId).
502 model_unavailableThe AI service could not complete the request. Retry with the same Idempotency-Key.
429 rate_limitedWait retryAfterSeconds and retry.

For 402 agent_paused the reason is one of not_subscribed, payment_pending, subscription_expired, subscription_canceled, credits_exhausted, billing_review, account_suspended, refunded or paused. The message explains it in plain words.

Good habits

  • Set a generous timeout (two minutes). An answer that uses several tools can take a while.
  • Send one message at a time per conversation.
  • Never show raw error codes to your customers; show your own friendly text.
  • Always send an Idempotency-Key when your code may retry; see Retries and idempotency.