Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.dolfinai.co/llms.txt

Use this file to discover all available pages before exploring further.

The Dolfin AR Agent lets your users create customers, products, and invoices through natural language. Instead of calling individual endpoints, you send a single user message to POST /agent/ar and the agent handles the rest. This guide walks through the same invoice flow as the Quick Start, but driven entirely through the agent.

Prerequisites

  • A Dolfin API key
  • An organisation already provisioned (see Client Integration)
  • A valid session token or API key for authentication
All requests below require the x-dolfin-api-key and x-dolfin-organisation-id headers. See Authentication for details.

How the Agent Works

Every turn is a single POST to /agent/ar with just two body fields:
FieldTypeNotes
messagestring, requiredThe user’s message for this turn
conversationIdUUID, optionalOmit on the first turn. Supply on every subsequent turn to continue the same thread
You do not send the full message history — Dolfin persists the conversation server-side and the agent loads it automatically from conversationId.

Response format

The response is a text/event-stream (SSE). Read events as they arrive:
EventPayloadWhen
conversation{ "id": "uuid" }Fired once, on the first turn only, before any content
(unnamed){ "content": "text chunk" }Streamed assistant text, one chunk per data frame
actionTool action objectWhen the agent runs a tool (e.g. created a customer)
(unnamed){ "done": true }Final frame — stream is complete
On error, the final frame is { "error": "message", "done": true }.

Persisting conversationId

On the first request, read the conversation SSE event and save its data.id. Echo that UUID back as conversationId on every follow-up POST to continue the same conversation.
async function chat(message, conversationId) {
  const res = await fetch('https://api.dolfinai.co/agent/ar', {
    method: 'POST',
    headers: {
      'x-dolfin-api-key': 'dol_live_abc123',
      'x-dolfin-organisation-id': '9a658587-fe02-402e-b1ac-bfaf53274ef8',
      'Content-Type': 'application/json',
      'Accept': 'text/event-stream',
    },
    body: JSON.stringify(conversationId ? { message, conversationId } : { message }),
  });

  let newConversationId;
  let assistantText = '';

  // Parse SSE frames
  const reader = res.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';
  for (;;) {
    const { value, done } = await reader.read();
    if (done) break;
    buffer += decoder.decode(value, { stream: true });

    let frameEnd;
    while ((frameEnd = buffer.indexOf('\n\n')) !== -1) {
      const frame = buffer.slice(0, frameEnd);
      buffer = buffer.slice(frameEnd + 2);

      let eventName = 'message';
      let dataLine = '';
      for (const line of frame.split('\n')) {
        if (line.startsWith('event: ')) eventName = line.slice(7);
        else if (line.startsWith('data: ')) dataLine = line.slice(6);
      }
      if (!dataLine) continue;
      const data = JSON.parse(dataLine);

      if (eventName === 'conversation') newConversationId = data.id;
      else if (eventName === 'action') handleAction(data);
      else if (data.content) assistantText += data.content;
      else if (data.done) return { conversationId: newConversationId, assistantText };
    }
  }
}
Once the first response returns a conversationId, the agent type is frozen on that conversation. Sending a request to POST /agent/ap with an AR conversation’s conversationId (or vice versa) returns 409 Conflict.

Conversation scoping

Conversations are scoped by:
  • Organisation — always. A conversation belongs to the organisation in x-dolfin-organisation-id and can’t be read or continued from another organisation.
  • User — only when the call is authenticated with a Bearer JWT. API-key calls have no user binding, so any caller with the same API key and organisation can continue an API-key conversation.

Step 1: Create a Customer

This is the first turn, so omit conversationId. The response’s conversation event gives you the ID to use for every subsequent turn.
curl -N -X POST https://api.dolfinai.co/agent/ar \
  -H "x-dolfin-api-key: dol_live_abc123" \
  -H "x-dolfin-organisation-id: 9a658587-fe02-402e-b1ac-bfaf53274ef8" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "message": "can you help me create a customer?"
  }'
SSE stream (excerpt):
event: conversation
data: {"id":"cf2d4a1e-7b39-4c82-a0d8-18a2b7c6d9e1"}

data: {"content":"I'd be happy to help"}

data: {"content":" you create a new customer!"}

data: {"content":" Please provide..."}

data: {"done":true}
The agent asks for details:
I’d be happy to help you create a new customer! Please provide the following details: Required:
  • Name — The customer’s full name or business name
Optional:
  • Email address
  • Phone number
  • Tax/VAT number
  • Address (line 1, line 2, city, state/county, postal code, country)
Now continue the conversation by sending the same conversationId back:
curl -N -X POST https://api.dolfinai.co/agent/ar \
  -H "x-dolfin-api-key: dol_live_abc123" \
  -H "x-dolfin-organisation-id: 9a658587-fe02-402e-b1ac-bfaf53274ef8" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "conversationId": "cf2d4a1e-7b39-4c82-a0d8-18a2b7c6d9e1",
    "message": "Joe Bloggs with email joebloggs@gmail.com"
  }'
The agent confirms before creating:
Here’s a summary of the customer I’ll create: Shall I go ahead and create this customer?
Confirm, and the agent runs the createCustomer tool and emits an action event:
event: action
data: {"type":"customer.created","customerId":"c3456789-abcd-ef01-2345-6789abcdef01", ...}

data: {"content":"Joe Bloggs has been created successfully!"}

data: {"done":true}

Step 2: Create a Product

Same conversationId, next message.
curl -N -X POST https://api.dolfinai.co/agent/ar \
  -H "x-dolfin-api-key: dol_live_abc123" \
  -H "x-dolfin-organisation-id: 9a658587-fe02-402e-b1ac-bfaf53274ef8" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "conversationId": "cf2d4a1e-7b39-4c82-a0d8-18a2b7c6d9e1",
    "message": "now create me a product called \"silver mirror\" of price 100 GBP"
  }'
The agent confirms the details:
Here’s a summary of the product I’ll create:
  • Name: Silver Mirror
  • Price: £100.00 GBP
  • Type: Product
Before I proceed, could you confirm:
  1. Is the type correct as Product (rather than Service)?
  2. Would you like to add a description?
After confirmation:
The Silver Mirror product has been created successfully!

Step 3: Create an Invoice

The agent remembers the customer and product from earlier in the conversation — you don’t need to pass any IDs.
curl -N -X POST https://api.dolfinai.co/agent/ar \
  -H "x-dolfin-api-key: dol_live_abc123" \
  -H "x-dolfin-organisation-id: 9a658587-fe02-402e-b1ac-bfaf53274ef8" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "conversationId": "cf2d4a1e-7b39-4c82-a0d8-18a2b7c6d9e1",
    "message": "create an invoice for Joe with 5x silver mirrors"
  }'
The agent looks up the customer and product, then confirms:
Here’s a summary of the invoice I’ll create:
  • Customer: Joe Bloggs
  • Product: Silver Mirror x5
  • Total: £500.00 GBP
Shall I go ahead and create this invoice?
After confirmation:
The invoice has been created successfully!
  • Invoice Number: INV-92631974
  • Customer: Joe Bloggs
  • Items: Silver Mirror x5
  • Total: £500.00 GBP
  • Status: Draft
Would you like me to send the invoice to Joe at joebloggs@gmail.com?
Because the conversation history is loaded server-side from conversationId, the agent resolves “Joe” and “silver mirrors” to the correct customer and product without you having to track IDs client-side.

Step 4: Send the Invoice

curl -N -X POST https://api.dolfinai.co/agent/ar \
  -H "x-dolfin-api-key: dol_live_abc123" \
  -H "x-dolfin-organisation-id: 9a658587-fe02-402e-b1ac-bfaf53274ef8" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "conversationId": "cf2d4a1e-7b39-4c82-a0d8-18a2b7c6d9e1",
    "message": "Sure, lets send it!"
  }'
The agent sends the invoice and confirms:
Invoice sent successfully!
  • Invoice: INV-92631974
  • Sent to: joebloggs@gmail.com
  • Amount: £500.00 GBP
  • Due Date: 14th May 2026

Full Conversation Flow

Here’s the complete exchange from start to finish:
TurnconversationId sent?User message
1No (first turn)“can you help me create a customer?“
2Yes”Joe Bloggs with email joebloggs@gmail.com
3Yes”now create me a product called “silver mirror” of price 100 GBP”
4Yes”create an invoice for Joe with 5x silver mirrors”
5Yes”Sure, lets send it!”

Managing Conversations

EndpointPurpose
GET /agent/conversations?agentType=ArList the caller’s AR conversations
GET /agent/conversations/{id}Get metadata for a single conversation
GET /agent/conversations/{id}/messagesPaged message history
PATCH /agent/conversations/{id}Rename a conversation
DELETE /agent/conversations/{id}Delete a conversation and its messages

Agent vs Direct API

Direct APIAR Agent
InterfaceIndividual REST endpointsConversational messages
ID managementYou track and pass IDs between callsAgent resolves names from conversation history
ConfirmationImmediate executionAgent confirms before acting
Best forProgrammatic automationInteractive user experiences

Next Steps

Quick Start (Direct API)

See the same flow using direct API calls.

API Reference

Explore the full API reference for all endpoints.