Idempotency
Network calls fail in the middle. Linnia makes command requests safe to retry, so a timeout on your side never turns into two connection requests on LinkedIn.
Idempotency keys
Section titled “Idempotency keys”Send an Idempotency-Key header (up to 200 characters) with any command:
curl -X POST https://api.linnia.ai/v1/accounts/$ACCOUNT/send_message \ -H "Authorization: Bearer $LINNIA_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: crm-task-55120-followup-1" \ -d '{"person":"sofia-reyes","text":"Thanks for connecting, Sofia."}'- The first request creates the job and answers
202with"created": true. - Any later request for the same account with the same key answers
200with"created": falseand the original job, whatever the body says. Nothing is sent twice.
With POST /v1/jobs you can pass the key in the body as idempotencyKey instead of the header.
Use a key that names the intent in your system, such as crm-lead-88412-connect, rather than a random value per attempt.
Automatic de-duplication
Section titled “Automatic de-duplication”Without a key, Linnia still protects you: the same command with the same input on the same account within a 15-minute window returns the existing job (200, created: false). Input is compared after normalising (key order doesn’t matter, and a profile URL equals its public identifier).
The MCP server relies on this too, which is why assistants are told to check get_job rather than call a write tool again.
What isn’t covered
Section titled “What isn’t covered”- Workflows (
POST /v1/accounts/{id}/workflows) always start a new job. UsedryRun: truefirst. - Approving twice is safe: the second call fails with
invalidParams(“This request was already approved”). - Creating webhooks, keys and automations isn’t idempotent; check the list before creating again.