What Makes an API Safe for AI Agents: Idempotency, Dry Runs, Fixable Errors, and Human Claim
Four mechanisms make an API safe for AI agents: idempotency keys, dry runs, errors that name the fix, and human claim. Exact codes from the WarpLink API.
TL;DR: An agent retries, guesses, and acts without a person watching. An agent-ready API gives it four things: safe retries (idempotency), a preview (dry run), errors that name the fix, and a way to start work that a person then claims. This post shows how WarpLink implements each, with the exact codes.
WarpLink is link infrastructure for mobile teams: deep linking, install attribution, and real-time analytics in one SDK. Its MCP server lets a coding agent register an app, create links, and verify a setup. An agent works differently from a person at a keyboard. It retries on a timeout, it tries a call to see what happens, and it cannot read a screenshot of an error. The mechanisms below are how we designed for that. Every behavior listed is in the live API docs.
Safe retries: idempotency keys
A retry of a create call must not make a second resource. Send an Idempotency-Key header on POST /v1/links or POST /v1/apps, or pass idempotency_key to the MCP tools create_link and create_app. The key is 1 to 255 printable ASCII characters you choose, such as a UUID.
| Situation | Response |
|---|---|
| Same key, same request | The first response, with its original status, and the header Idempotent-Replayed: true. MCP results carry _meta["warplink/idempotent_replayed"]: true. |
| Same key, different request | 422 IDEMPOTENCY_KEY_REUSED |
| Retry while the first call still runs | 409 IDEMPOTENCY_IN_PROGRESS. Wait a second and retry with the same key. |
First response was a 5xx or 429 | Not remembered, so the retry runs again. |
Keys are remembered for 24 hours, scoped to your organization, the API key, and the endpoint. The full rules are in the API reference.
Dry runs: see the result before it exists
An agent should be able to ask "what would happen" without saving anything. Add ?dry_run=true to POST /v1/links, POST /v1/apps, and PATCH /v1/links/{id}, or pass dry_run: true to create_link, create_app, and update_link.
WarpLink runs every check a real call runs: authentication, role, validation, plan limits, link safety, and the slug, handle, and duplicate checks. The answer is 200 with the result the call would have returned:
{ "dry_run": true, "result": { "...": "what the real call would return" } }
Nothing is saved, no audit entry is written, and no idempotency key is stored. An agent previews, checks the result with the person if the change matters, then repeats the call without dry_run.
Errors that say how to fix them
The error shape did not change: { "error": { "code", "message" } }. When we know the remedy, the error gains details.fix and details.docs_url:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request body",
"details": {
"fields": [{ "field": "destination_url", "message": "Invalid URL" }],
"fix": "Fix each field listed in `details.fields` and send the request again.",
"docs_url": "https://warplink.app/docs/errors#validation_error"
}
}
}
The MCP server puts Fix: ... in the error text and returns the same fields in structuredContent.error, so a client that reads text and a client that reads structure both get the remedy. Every code in the errors reference carries a fix, and the table on that page reads the same catalog that fills the response. An agent applies the fix, then retries. This is the cheapest mechanism on the list and it removes most guessing.
Start now, a person claims later
An agent often starts before its user has an account. POST /v1/agent/signup needs no credential. The agent sends email and agent_name, and WarpLink creates a Free workspace, emails the claim link to the person (never to the agent), and returns an MCP access token. The response never contains the claim link, so the agent cannot claim the workspace itself.
| Until the person claims the workspace | Behavior |
|---|---|
| Apps and links | 1 app, 10 links |
| Link state | Every link stays paused. activate_link and update_link with is_active: true return CLAIM_REQUIRED. |
| Keys and domains | App-tied SDK keys only. API keys and custom domains return CLAIM_REQUIRED. |
| Token | Works on the MCP server only, not on the REST API. |
| Lifetime | The workspace is removed after 7 days, with one reminder email about 2 days before. |
| Rate limits | 3 workspaces an hour and 10 a day per client address, and one claim email a day per email address. |
The design is simple to state: the agent can build, and only a person can make links live. At the claim, the workspace becomes the person's, its links turn on, and the agent's connection moves into Settings > Connected AI, where the person can revoke it. The endpoint is documented in Agent sign-up.
Setup that verifies itself
An agent needs to know when it is done and when to stop. verify_setup returns a list of checks, each with a status of pass, fail, warn, needs_human, or skipped, and a fix on each check that needs one. The agent applies each fix and calls the tool again. When only needs_human checks remain, it stops and reports them: a device tap, the first click, the SDK connecting from a real device, or claiming the workspace. The agent knows exactly which steps are the person's. The walkthrough is in set up deep linking with Claude Code.
Keys an agent can hold
Credentials need the same care. An agent connected over OAuth can create an SDK key tied to one app with create_key. The key has the fixed SDK scopes, works only on the SDK routes, and never expires. An API key made by an assistant never gets keys:read or keys:write scopes and lives at most 90 days. list_keys and GET /v1/keys show created_via, so the person can see which keys an agent made. The MCP server refuses SDK keys with 403 SDK_KEY_ROUTE_FORBIDDEN. See Authentication for scopes and rate limiting for the 60 requests a minute per credential.
Docs agents can read
An agent that cannot read your docs guesses. Every docs page is also available as Markdown at /docs/<page>.md, and every blog post at /blog/<slug>.md. The site serves llms.txt and llms-full.txt. The MCP server offers resources such as warplink://docs/errors and warplink://docs/setup-guide, which a client can attach as context.
The checklist
| Mechanism | Why an agent needs it | WarpLink endpoint or tool |
|---|---|---|
| Idempotency keys | A retry must not create a second resource | Idempotency-Key on POST /v1/links and POST /v1/apps, idempotency_key on create_link and create_app |
| Dry run | Preview the result before it is saved | ?dry_run=true on three REST calls, dry_run on create_link, create_app, update_link |
| Fixable errors | Apply the remedy instead of guessing | details.fix and details.docs_url, Fix: in MCP text |
| Human claim | The agent builds, a person makes it live | POST /v1/agent/signup, CLAIM_REQUIRED |
| Self-verifying setup | Know when to stop and what is left | verify_setup, GET /v1/apps/{id}/setup-check |
| Scoped keys | A leaked key reaches little | App-tied SDK keys, assistant API keys without keys:*, created_via |
| Readable docs | Read the rule instead of guessing it | /docs/<page>.md, /blog/<slug>.md, llms.txt, MCP resources |
Frequently Asked Questions
What makes an API agent-ready?
An agent-ready API gives an AI agent four things: safe retries through idempotency keys, a preview through dry runs, errors that name the fix, and a way to start work that a person then claims. WarpLink implements all four on the REST API and the MCP server, and adds setup checks that tell the agent when to stop.
Why do AI agents need idempotency keys?
An agent retries when a connection drops or a response is slow, and a plain retry of a create call makes a second resource. With an idempotency key, a repeat of the same request returns the first response instead. WarpLink accepts an Idempotency-Key header on POST /v1/links and POST /v1/apps, and an idempotency_key argument on the create_link and create_app MCP tools. Keys last 24 hours.
What does a dry run return in the WarpLink API?
A dry run returns 200 with the result the call would have returned, wrapped as { "dry_run": true, "result": ... }, and saves nothing. WarpLink runs every check a real call runs: authentication, role, validation, plan limits, link safety, and the slug, handle, and duplicate checks. Add ?dry_run=true to POST /v1/links, POST /v1/apps, and PATCH /v1/links/{id}, or pass dry_run: true to create_link, create_app, and update_link.
How can an AI agent sign up for WarpLink without the person's password?
The agent calls POST /v1/agent/signup with the person's email address and the agent's name. WarpLink creates a Free workspace, emails the claim link to the person and never to the agent, and returns an MCP access token. The person opens the email, signs in or creates an account, and chooses Claim workspace. The agent never sees a password.
What can an unclaimed workspace do?
An unclaimed workspace holds 1 app and 10 links, and every link stays paused. Activating a link, creating an API key, or adding a custom domain returns CLAIM_REQUIRED. The agent can still create app-tied SDK keys. The workspace is removed after 7 days, with one reminder email about 2 days before.
How does an agent know how to fix a failed API call?
Every error keeps the shape { error: { code, message } } and, when WarpLink knows the remedy, adds details.fix and details.docs_url. The MCP server puts Fix: followed by the same text in the error message and returns the fields in structuredContent.error. The agent applies the fix before it retries.
Related Guides
- WarpLink for AI agents
- Set up deep linking with Claude Code
- AI agents guide
- Agent sign-up API
- Errors reference
Create a free account and connect your agent.
Try WarpLink on one real link
Deep linking, install attribution, and real-time analytics in one SDK. Free for 10K clicks a month, no sales call.
Stuck on setup? Email support@warplink.app and we will help you get one real link working.
WarpLink Team
Building affordable, reliable link infrastructure for mobile teams. Deep linking, install attribution, and real-time analytics in one SDK.
Related Posts
Set Up Deep Linking With Claude Code: From Empty Project to Verified Link
Connect Claude Code to the WarpLink MCP server and let it register your app, add the SDK, create a link, and run verify_setup. Commands and outputs inside.
5 Best Deep Linking and Attribution MCP Servers in 2026
Five MCP servers for deep links and mobile attribution in 2026, compared on tools, sign-in, and access: WarpLink, Grovs, Kochava, AppsFlyer, Branch.
WarpLink Analytics: What Changed, and Why
The rebuilt Analytics page leads with the answer: how clicks moved against the previous period, why, and which links need attention. Also on MCP and REST.