The shape of the integration
Keep a layer between the agent and your core systems. That layer owns the policy (which customer, which action, which limits), the credential and the logging, so the agent never needs broad access.Start from tasks, not from your API
List the customer tasks you want the agent to complete, then derive the endpoints. This keeps the surface small and easy to justify in a security review.
Build one endpoint per task step rather than exposing a generic “update customer” call. A narrow endpoint is easier to secure, test and explain.
Separate reads from writes
Reads give the agent context: plan, account state, recent orders. They should be safe to call often, side-effect free, and useGET. Writes change state: cancel, refund, update. They should be few, explicit, and use POST or PUT. Keep them on separate credentials or scopes so a lookup integration can never move money.
Scoping and least privilege
- Give the agent its own service identity. Never reuse an employee account or an admin key. You want to revoke it, rate-limit it and audit it on its own.
- Scope per endpoint. A credential for order lookups should not reach the refunds endpoint.
- Bind every call to the customer in the conversation. Enforce on the server that the record requested belongs to the verified customer. Don’t rely on the agent to pass the right ID: inputs come from conversation text, and a customer can type someone else’s email.
- Enforce limits on the server. Refund caps, allowed plan changes and eligibility rules belong in your API, so they hold even if the agent’s configuration is wrong.
- Use separate credentials per environment (sandbox, staging, production).
Authentication patterns
Whichever you choose, validate the credential on every request and reject anything else with
401 Unauthorized.
Idempotency keys for writes
Networks time out and calls get retried. Without protection, a retry after a slow response can issue a second refund or a second replacement card. An idempotency key fixes this: the caller sends a unique key with each write, and your server stores the result for that key. A repeated request with the same key returns the stored result instead of acting again.Confirmation before irreversible actions
Classify every write as reversible (address change before dispatch), reversible at a cost (cancellation with a fee) or irreversible (refund, data deletion, transfer). For the last two:- Read before you write. Check eligibility and current state with a read endpoint first.
- Confirm with the customer using a plain summary of exactly what will happen: “I’ll cancel your Pro plan today. Your final charge is on June 15. Should I go ahead?”
- Re-check preconditions on the server at write time, since state can change during the conversation.
- Hand off above a threshold. Above your limit, the endpoint should refuse with a clear reason, and the agent should route the case to a person.
Response shape
The fields you return become what the agent can reason about and say. Keep responses small, flat and predictable.- Return only what the task needs. Every extra field is data the agent might repeat to the customer.
- Use explicit fields.
"account_closed": trueis clearer than inferring state from a status code buried in a nested object. - Keep names and types stable. The same field, same case style, same type, in every response. Return
nullrather than omitting a field. - Prefer low-cardinality enums for status fields, with any display label in a separate field.
- Include a human-readable reason, written so it could be shown to a customer.
Error design
Separate business outcomes from protocol failures. “Not eligible for a refund” is a valid answer: return200 OK with success: false, a stable error_code and a message. Reserve 4xx and 5xx for bad input, missing auth and server errors. The code lets the agent branch (offer store credit, hand off); the message lets it explain. Never return stack traces in error bodies.
Latency budgets
The customer is waiting while the agent calls you, often across several calls in one turn. Set a budget per endpoint, keep reads faster than writes, and time out rather than hang. Avoid endpoints that fan out to many downstream services. For work that genuinely takes long (a document check, a bank transfer), accept the request quickly, return a reference and status, and let the agent tell the customer when to expect the result.Rate limits
Agent traffic follows conversation volume, so it spikes during outages and campaigns. Give the agent’s credential its own limit so it can’t starve other clients, return429 with Retry-After, and share the limit with whoever configures the agent.
Sandbox and test environments
Provide a sandbox that implements the same contract as production, with test customers that cover your real cases: active, closed, high-risk, several cards, no orders. Add a way to force failures (timeouts,500s, business refusals) so you can test how the agent recovers. Never point a new write integration at production until it has passed a representative set of test conversations in the sandbox.
Audit logging
Log every agent call so any action can be traced back to a conversation.
Redact secrets and sensitive values such as full card numbers, and keep logs for as long as your own retention policy requires.
Readiness checklist
Common mistakes
- Exposing the internal admin API with one broad key.
- Trusting the customer ID the agent passes without checking it on the server.
- Retries without idempotency, which turns a timeout into a duplicate refund.
- Business refusals as
500s, so the agent can’t tell “not eligible” from “broken”. - Nested, changing response shapes that break the agent’s field mappings after a release.
- Testing only the happy path in the sandbox.
Doing this in Fini
In Fini (usefini.com), your endpoints plug in like this:- The contract Fini expects: HTTPS only, JSON in and out, an
x-api-keyheader on every request, flat responses with stable fields, and a target of under two seconds for reads and under five seconds for writes. Write responses returnsuccessandmessage, pluserror_codeon failure. See the API contract, which also lists what to send your Fini contact, including rate limits and expected latency. - Reads and writes: read endpoints become Attributes, which run on every message; write endpoints become Actions, which run only when a Tool node in a published Rulebook rule invokes them. Test an Action with sample inputs using the Play button before saving.
- Regression tests and live calls: Test Suite uses recorded or mock Action responses and never calls your endpoints, so it checks the agent’s decisions (which Action, when, and how it handles a Success or Failure response) but not your API itself. Check the live endpoints end to end against your sandbox, then in a controlled pilot.
- Idempotency on MCP tools: if a write tool on a connected MCP server declares an
idempotency_keyinput, Fini generates and injects one per conversation and intent. See MCP Connections. - Keys for calling Fini: if your systems also call Fini’s public APIs, use workspace keys from Deploy → API Keys with only the
readorwritescope they need. See API Keys. - A worked example: the card replacement walkthrough chains a lookup attribute, two write Actions, a Form for the shipping address and a Reply Behavior fraud gate, built in a sandbox first.
Related
API contract
Endpoint requirements, sample requests and responses, and the handoff checklist.
Actions
Typed API calls the agent runs from a Rulebook Tool node.
Card replacement walkthrough
Two chained write Actions with a fraud gate, end to end.
Designing an escalation policy
Which conversations, including high-value actions, must reach a person.

