Idempotency
Import and export job creation endpoints accept idempotency keys so network retries do not queue duplicate work. This guide explains when to use a key, how to choose one, and how to store the key with your own job record.
Use Idempotency for Async Job Creation
Idempotency protects create-style requests from accidental duplication. In Mailrith's public API, idempotency is most important when queueing subscriber import and export jobs because those jobs can continue doing significant work after the request returns.
If your integration sends a job creation request and the network times out, your integration may not know whether Mailrith received the request. Repeating the request with the same Idempotency-Key lets Mailrith return the original job response instead of creating another job.
Use idempotency keys for import and export job creation whenever the caller, queue worker, or HTTP client might retry a request automatically.
- Create your own local job record before sending the Mailrith request.
- Generate one idempotency key for that local job.
- Send the Mailrith import or export request with
Idempotency-Keyand the job payload. - If the request succeeds, store the returned Mailrith job ID.
- If the request times out, retry with the same key and the exact same payload.
- If the CSV, mappings, or export filters change, create a new local job and a new idempotency key before sending another request.
- Monitor the job as described in Import and Export Jobs.
- Generate one idempotency key for one logical job submission.
- Reuse the same key only for retries of the exact same request body.
- Store the key with your own job record so a queue worker can retry safely after a crash.
- Use a new key when the CSV content, mappings, filters, or export selection changes.
- Do not use one long-lived key for every import or export. A long-lived key would make different jobs look like the same request.
/v1/jobs/subscriber-exports Create a subscriber export job
Queues an asynchronous subscriber export for the authenticated workspace. Requires `jobs:write` and `subscribers:read` because the finished file contains subscriber data.
View Schema /v1/jobs/subscriber-exports/{job_id} Get a subscriber export job
Returns the current state of a previously created export job. Requires `jobs:read` and `subscribers:read` because completed jobs include a subscriber CSV download URL.
View Schema /v1/jobs/subscriber-imports Create a subscriber import job
Queues an asynchronous import job that creates or updates subscribers from CSV text.
View Schema /v1/jobs/subscriber-imports/{job_id} Get a subscriber import job
Returns the current state of a previously created import job.
View SchemaKeep Retries Safe
A safe retry pattern starts before the HTTP request is sent. First create your own local job record, then generate an idempotency key, then send the Mailrith request with that key.
If the request succeeds, store Mailrith's returned job ID beside your own job record. If the request times out, retry with the same key and the same request body. If Mailrith already created the job, Mailrith can return the original response.
If you change the payload after a failed attempt, create a new idempotency key before retrying. A changed payload is no longer the same logical job.
- Good key examples:
import_2026_04_25_crm_001, a UUID, or your own queue job ID. - Bad key examples:
import,retry, the workspace ID, or the API key. - Keep idempotency keys out of user-visible copy. They are operational identifiers, not labels.
- Log the idempotency key with your job ID so you can trace repeated attempts.
curl -X POST https://api.mailrith.com/v1/jobs/subscriber-imports \
-H "Authorization: Bearer mrk_example_secret_key" \
-H "Idempotency-Key: import-2026-04-11-website-signups" \
-H "Content-Type: application/json" \
-d '{
"csv_text": "Email,Name,Country,Subscriber Status\nada@example.com,Ada Lovelace,DE,Active",
"mappings": [
{
"csv_column": "Email",
"field": { "type": "email" }
},
{
"csv_column": "Name",
"field": { "type": "name" }
},
{
"csv_column": "Country",
"field": { "type": "country" }
},
{
"csv_column": "Subscriber Status",
"field": { "type": "subscriber-status" }
}
],
"new_tag_name": "Website Signup"
}' Need Help Shipping an Integration?
Reach the Mailrith team if you need help planning a sync, validating a webhook flow, or troubleshooting a request.