The Cases API exposes your Amazon Seller Central support, compliance, and account-health cases as an API (and matching MCP tools), scoped to your account like the rest of the Cajari API.
It has two halves that behave differently:
synced_at timestamp telling you how fresh the data is.Same as the rest of the Cajari API. Use your API Key as a Bearer token in the HTTP Authorization header. Every call is scoped to your account — cases from other accounts are never visible.
All identifiers are opaque IDs. List endpoints paginate with
limit and cursor.
curl https://api.cajari.com/v2/cases \
-H "Authorization: Bearer <your_api_key_here>"
GET /v2/cases
Lists cases for your account. Defaults to open cases, most-recent reply first.
| Parameter | Description |
|---|---|
merchant_marketplace_id | Restrict to one merchant marketplace. Default: all of your MMs. |
status | open, pending_amazon, pending_merchant, resolved, closed, or all. Default open. Comma-separated for multiple. |
category | Filter to categories: fba_inventory, listing, account_health, feedback, other. Comma-separated. |
exclude_category | Exclude categories (e.g. fba_inventory to drop reimbursement claims). Comma-separated. |
asin | Only cases referencing this ASIN (matches any ASIN on the case, not just the primary). |
shipment_id | Only cases referencing this FBA shipment ID. |
updated_since | Only cases with activity at/after this ISO-8601 time. |
created_since | Only cases created at/after this ISO-8601 time. |
sort | last_reply_desc (default) or created_desc. |
limit, cursor | Pagination. |
curl "https://api.cajari.com/v2/cases?status=open&sort=last_reply_desc" \
-H "Authorization: Bearer <your_api_key_here>"
{
"synced_at": "2026-10-08T17:02:11Z",
"cases": [
{
"id": "22451523931",
"merchant_marketplace_id": "a1b2c3d4",
"status": "pending_amazon",
"amazon_status": "PendingAmazonAction",
"subject": "FBA19L555DM7 - Missing Items from Inbound",
"asin": "B0XXXXXXXX",
"asins": ["B0XXXXXXXX"],
"shipment_id": "FBA19L555DM7",
"category": "fba_inventory",
"created_at": "2026-10-07T06:18:53Z",
"last_reply_at": "2026-10-07T06:19:05Z",
"escalated": false,
"synced_at": "2026-10-08T17:02:11Z"
}
],
"next_cursor": "..."
}
status is a normalized value; amazon_status is Amazon's
raw value. asin, shipment_id, and category are
parsed from the case subject and thread (best-effort; null/other
when nothing obvious is found). The list view omits the message thread — fetch a
single case for that.
{
"id": "22451523931",
"merchant_marketplace_id": "a1b2c3d4",
"status": "pending_amazon",
"amazon_status": "PendingAmazonAction",
"subject": "FBA19L555DM7 - Missing Items from Inbound",
"asin": "B0XXXXXXXX",
"asins": ["B0XXXXXXXX"],
"shipment_id": "FBA19L555DM7",
"category": "fba_inventory",
"created_at": "2026-10-07T06:18:53Z",
"last_reply_at": "2026-10-07T06:19:05Z",
"escalated": false,
"messages": [
{
"id": "...",
"direction": "inbound",
"author": "Amazon",
"sent_at": "2026-10-07T06:19:05Z",
"body": "...",
"has_attachments": true,
"attachments": [
{
"file_name": "invoice-12345.pdf",
"content_type": "application/pdf",
"download_url": "/v2/cases/22451523931/attachments/0A1B2C3D"
}
]
}
],
"synced_at": "2026-10-08T17:02:11Z"
}
Each message lists its attachments' file_name, content_type,
and a download_url. We re-host attachments in our own storage (Amazon's URLs
expire within minutes), so the link is stable. download_url is
null until the file has been captured — we capture attachments for
non-resolved cases.
GET a download_url (with your Bearer token) to stream the
file back with its original content type.
These endpoints are still in design and not yet callable; the shape below is proposed and may change.
A write request creates a submission and returns 202 Accepted
with the submission in status: received. Poll
GET /v2/case_submissions/{id} (or register a webhook) until the submission reaches
a terminal status. A write never returns the final result directly.
POST /v2/cases/{id}/replies
Adds a reply to an existing case. Send an Idempotency-Key header (or
client_reference_id) so a retry returns the original submission instead of
posting a second reply.
curl https://api.cajari.com/v2/cases/22451523931/replies \
-H "Authorization: Bearer <your_api_key_here>" \
-H "Idempotency-Key: 9f1c-..." \
-H "Content-Type: application/json" \
-d '{"body": "Following up on the reimbursement."}'
{
"submission": {
"id": "sub_01J...",
"type": "reply",
"case_id": "22451523931",
"status": "received",
"handling": null,
"attempts": 0,
"received_at": "2026-10-08T17:05:00Z",
"last_attempt_at": null,
"completed_at": null,
"request": { "body": "Following up on the reimbursement." },
"result": null,
"error": null,
"poll_url": "/v2/case_submissions/sub_01J..."
}
}
GET /v2/case_submissions/{id}
The status tracker you poll after a write.
GET /v2/case_submissions lists your submissions, filterable by
status, type, case_id, and
created_since.
{
"submission": {
"id": "sub_01J...",
"type": "reply",
"case_id": "22451523931",
"status": "succeeded",
"handling": "automatic",
"attempts": 1,
"received_at": "2026-10-08T17:05:00Z",
"last_attempt_at": "2026-10-08T17:12:30Z",
"completed_at": "2026-10-08T17:12:33Z",
"request": { "body": "Following up on the reimbursement." },
"result": {
"case_id": "22451523931",
"reply_id": "...",
"message": "Reply posted to Amazon."
},
"error": null
}
}
A submission tells you three things at a glance: that we received your request, whether we have attempted it, and how it ended.
| Status | Meaning | Received? | Attempted? | Result known? |
|---|---|---|---|---|
received | Stored and accepted. Not yet worked. | Yes | No | No |
queued | Waiting for a processing window. | Yes | No | No |
processing | Actively being submitted to Amazon. | Yes | In progress | No |
succeeded | Amazon accepted it. result is populated. | Yes | Yes | Yes |
failed | Attempted and rejected, or errored. error is populated. May be retried. | Yes | Yes | Yes |
canceled | Canceled before completion. | Yes | Maybe | Yes |
Supporting fields: received_at (we accepted it), attempts +
last_attempt_at (whether/when we tried), and completed_at +
result/error (the outcome). The handling field
(automatic, manual, or null) indicates how a submission
was processed; it does not change the status flow.
Case notifications go to a dedicated Cases webhook URL, configured separately from your report/result webhook — so these never reach a receiver that only expects report payloads. If no Cases webhook URL is set, nothing is sent (poll instead).
We POST a case event when Amazon activity lands — a new case
(case.created) or a new Amazon reply on an existing case (case.reply)
— so you're notified within minutes instead of polling. The body is
{ "event": "...", "sent_at": "...", "case": { ... } } where case is
the same object returned by the list endpoint. (Once asynchronous replies are live, their status
transitions post here too.)
Requests carry Authorization: Bearer <md5 of your API key> plus
X-Cajari-Webhook: case and X-Cajari-Event: case.created|case.reply
headers, so even on a shared endpoint they're unambiguous — the report webhook sends no
X-Cajari-* headers.
Each endpoint has a matching MCP tool:
list_casesget_casereply_to_case — returns a submissionget_case_submissionlist_case_submissionsThe Cases API is being rolled out in stages: