For the system that acts on a customer's behalf: one gateway to their whole CRM, read and write. Every write is reversible, and nothing here reaches their customers by accident.
This is Axiro's agent integration — one of several ways in. Web forms, the chat widget and WhatsApp are separate channels aimed at the end customer rather than at an integrator, and are set up by the Axiro administrator in the app itself. If you are wiring up a system that acts for a business, you are in the right place.
axa_4136ae99e21f46f4940c58ac18353545_7cyBFRVkVSJeqOg-pzJI5PfBYezSGBHtLi7pDCk6xKc
Throwaway data, reseeded regularly, 30 requests/minute. Everything you write here can be undone with one call — see Undo below.
Use the sandbox key above to explore. For a real customer, their Axiro
administrator issues the key — no request to us, no waiting: in Axiro under
Bridge › Ladder › External agents, or through
POST /external-agents with their own login. The key is shown once.
Two things they set at the same time, and both matter to you: whether your agent may
write to the CRM, and at which level. Reading works right away; writing needs the
level set to gedelegeerd or autonoom. Ask for both, or your
first write comes back as a 403.
No signup, no SDK. One header, one endpoint:
curl -s https://developers.axiro.nl/v1/agent/crm/relation?limit=3 \
-H 'X-Axiro-Agent-Key: axa_4136ae99e21f46f4940c58ac18353545_7cyBFRVkVSJeqOg-pzJI5PfBYezSGBHtLi7pDCk6xKc'
Writing looks the same. Note what comes back: a batch_id and the call that
undoes it.
curl -s -X POST https://developers.axiro.nl/v1/agent/crm/relation \
-H 'X-Axiro-Agent-Key: axa_4136ae99e21f46f4940c58ac18353545_7cyBFRVkVSJeqOg-pzJI5PfBYezSGBHtLi7pDCk6xKc' \
-H 'Content-Type: application/json' \
-d '{"data": {"display_name": "Acme BV", "email": "hello@acme.example"}}'
Relations, opportunities, offers, projects, tickets, articles, orders, work orders, time entries, contracts and shipments — all through the same shape:
| What | Call |
|---|---|
| What can I do, right now? | GET /v1/agent/crm/objects |
| List | GET /v1/agent/crm/{object} |
| One | GET /v1/agent/crm/{object}/{id} |
| Create (one, or up to 200) | POST /v1/agent/crm/{object} |
| Change | PATCH /v1/agent/crm/{object}/{id} |
| Verbs (move stage, add line, plan) | POST /v1/agent/crm/{object}/{id}/actions/{action} |
| Views without an id (forecast, board) | GET /v1/agent/crm/{object}/views/{view} |
GET /v1/agent/crm/objects is the real contract: it lists every object, verb,
action and filter, and whether your key is allowed to use it. Start there rather
than with this page.
Every write belongs to a batch, even a single row. The response carries the batch id and the path to reverse it:
POST /v1/agent/crm/batches/{batch_id}/rollback
Rollback restores only the fields that batch changed — not the whole row. Someone else may have touched it in the meantime, and their work is not ours to undo.
A 403 is usually one of these, and the message says which:
| Layer | Meaning |
|---|---|
| Plan | The tenant does not have that module. 403 entitlement_required
is normal, not an outage — build for it. |
| Agent flag | Writing is off for this key (can_write_crm). |
| Level | Writing needs gedelegeerd or autonoom for the
crm.write capability; assisted may only read. |
Every text field is scored for prompt-injection patterns. The score never blocks your call —
it travels back in content_risk and is recorded with the batch. Treat text you
read from us the same way.
| Limit | Value |
|---|---|
| Requests per minute | Per key; 429 with Retry-After |
| Rows per create | 200 |
| Text field | 20 000 characters |
| Body | 5 MB |
Send an idempotency_key with a write and replaying it is free: the same key
returns the same batch instead of writing twice. After a timeout, just retry.
We push four events to your callback_url, signed with
X-Axiro-Signature: sha256=<hmac> over the raw body:
approval.decided, agent.revoked,
message.received and marketing.request.updated. Each one
also has a feed you can poll, so a missed webhook is never a lost event.
When one does not arrive, you do not have to guess:
| What | Call |
|---|---|
| Did you send anything? | GET /v1/agent/webhooks/deliveries |
| What was in it? | GET /v1/agent/webhooks/deliveries/{id} |
| Send it again | POST /v1/agent/webhooks/deliveries/{id}/replay |
A delivery records the status code, how long it took, and the exact payload —
but never the signature itself: stored next to the payload it would make your
secret easier to attack. A replay sends the same event with a fresh
timestamp, so it still passes replay protection on your side, and it is marked
replay_of so you can tell it apart from a new event.
In the sandbox nothing is actually sent — but the delivery is recorded, so you can build your receiver against the real payload shape before pointing it at production.
Two actions are disabled here, because they reach
the real world: offer.send sends an actual e-mail, and
shipment.buy_label buys a shipping label that costs actual money. Everything
else behaves exactly as it does in production.
The sandbox also has every module switched on so this page
can show them all. A real tenant usually has fewer — so do handle
403 entitlement_required before you go live.
| Code | What happened | What to do |
|---|---|---|
401 | Missing or unknown key | Check the
X-Axiro-Agent-Key header. |
403 | Plan, agent flag, level, IP allow-list, or a module switched off by the tenant | Read the message; call /crm/objects to see what this
key may do. |
404 | Unknown object, action or view | The message lists the valid ones. |
422 | Missing or invalid field, unknown filter | The message names the field. Unknown filters fail loudly on purpose — silence would look like a filter that works. |
429 | Rate limit | Wait Retry-After seconds. |
Generated from the OpenAPI document, so it cannot drift from the running API. Use “Test Request” to try a call with the key above.