Warranty claims
Warranty claims track post-repair issues on tickets that are still inside your shop’s warranty window. Coverage is derived: a ticket is covered when the shop’s warranty period, counted from the ticket’s latest paid invoice, has not yet expired. A claim opens against a covered ticket, moves through a status lifecycle — open → approved / rejected, then approved → resolved / rejected — and can link the no-charge rework ticket created to fix the issue.
The warranty claim object
Section titled “The warranty claim object”{ "object": "warranty_claim", "id": 27, "ticket_id": "TK-10042", "rework_ticket_id": "TK-10113", "status": "approved", "reason": "Screen developed dead pixels two weeks after replacement.", "resolution_notes": null, "warranty_expires_at": "2026-08-30T00:00:00.000Z", "created_at": "2026-07-01T15:20:00.000Z", "resolved_at": null}| Field | Type | Description |
|---|---|---|
id | integer | Unique claim ID |
ticket_id | string | The original (covered) ticket |
rework_ticket_id | string|null | The linked no-charge rework ticket, when one exists |
status | string | open, approved, rejected, or resolved |
reason | string|null | Why the claim was opened |
resolution_notes | string|null | Notes recorded while resolving |
warranty_expires_at | string|null | The coverage expiry snapshotted when the claim opened |
created_at | string|null | ISO-8601 creation timestamp |
resolved_at | string|null | ISO-8601 resolution timestamp |
List warranty claims
Section titled “List warranty claims”GET /api/v1/warranty_claimsReturns a cursor-paginated list of warranty claims, newest first. Filter by ticket_id or status.
Scope required: warranty.read
Query parameters
Section titled “Query parameters”| Parameter | Type | Description |
|---|---|---|
ticket_id | string | Filter to one ticket’s claims |
status | string | Filter by claim status: open, approved, rejected, resolved |
limit | integer | Page size, 1–100 (default: 25) |
cursor | string | Opaque cursor from a previous response’s next_cursor |
curl "https://app.benchkey.com/api/v1/warranty_claims?status=open" \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"Node.js
Section titled “Node.js”const res = await fetch( "https://app.benchkey.com/api/v1/warranty_claims?status=open", { headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" } });const { data, has_more, next_cursor } = await res.json();Response
Section titled “Response”{ "object": "list", "data": [ { "object": "warranty_claim", "id": 27, "status": "open", "..." } ], "has_more": false, "next_cursor": null}See Pagination for how to page through results.
Retrieve a warranty claim
Section titled “Retrieve a warranty claim”GET /api/v1/warranty_claims/:idReturns a single claim.
Scope required: warranty.read
curl "https://app.benchkey.com/api/v1/warranty_claims/27" \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"Response
Section titled “Response”Returns the warranty claim object. Returns 404 if no claim with that ID exists.
Look up active warranty coverage
Section titled “Look up active warranty coverage”GET /api/v1/warranty_claims/activeReturns the active warranty coverages for exactly one of: a ticket (ticket_id), a customer email (customer), or a customer phone (phone — the same lookup the in-app intake banner uses). Coverage is derived from the shop’s warranty window and each ticket’s latest paid invoice; expired or never-covered tickets yield an empty list.
Customer and phone lookups return at most 5 coverages.
Scope required: warranty.read
Query parameters
Section titled “Query parameters”Supply exactly one:
| Parameter | Type | Description |
|---|---|---|
ticket_id | string | Look up one ticket’s coverage |
customer | string | Look up by customer email |
phone | string | Look up by customer phone |
curl "https://app.benchkey.com/api/v1/warranty_claims/active?customer=jane.smith@example.com" \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"Response
Section titled “Response”{ "object": "list", "data": [ { "object": "warranty_coverage", "ticket_id": "TK-10042", "customer_name": "Jane Smith", "active": true, "expires_at": "2026-08-30T00:00:00.000Z", "terms_summary": "90-day limited warranty" } ], "has_more": false, "next_cursor": null}| Field | Type | Description |
|---|---|---|
ticket_id | string | The covered ticket |
customer_name | string|null | The ticket’s customer |
active | boolean | Always true in this list — expired coverage is omitted |
expires_at | string | ISO-8601 coverage expiry |
terms_summary | string | Human summary of the shop’s warranty terms (e.g. "90-day limited warranty") |
Open a warranty claim
Section titled “Open a warranty claim”POST /api/v1/warranty_claimsOpens a claim against a ticket whose derived warranty is active (the shop’s warranty window counted from the ticket’s latest paid invoice). Fails with 409 when the ticket has no warranty, the warranty has expired, or the ticket already has an open/approved claim.
Scope required: warranty.write
Send an Idempotency-Key header to make retries safe. See Idempotency.
Request body
Section titled “Request body”| Field | Required | Type | Description |
|---|---|---|---|
ticket_id | yes | string | The covered ticket’s ID |
reason | no | string|null | Why the claim is being opened (max 1000 characters) |
curl -X POST https://app.benchkey.com/api/v1/warranty_claims \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: claim-TK-10042-$(uuidgen)" \ -d '{ "ticket_id": "TK-10042", "reason": "Screen developed dead pixels two weeks after replacement." }'Node.js
Section titled “Node.js”const res = await fetch("https://app.benchkey.com/api/v1/warranty_claims", { method: "POST", headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa", "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID(), }, body: JSON.stringify({ ticket_id: "TK-10042", reason: "Screen developed dead pixels two weeks after replacement.", }),});const claim = await res.json(); // HTTP 201, status: "open"Response
Section titled “Response”Returns the opened warranty claim object with HTTP 201 and status: "open".
Update a warranty claim
Section titled “Update a warranty claim”PATCH /api/v1/warranty_claims/:idTransition the claim’s status, set resolution notes, or link/clear the no-charge rework ticket. Legal status moves: open → approved | rejected, approved → resolved | rejected — an illegal move returns 409. Setting rework_ticket_id to null clears the link; a ticket already linked to another claim returns 409.
Scope required: warranty.write
Request body
Section titled “Request body”At least one of:
| Field | Type | Description |
|---|---|---|
status | string | open, approved, rejected, or resolved (subject to the legal transitions above) |
resolution_notes | string|null | Notes recorded on the claim (max 1000 characters) |
rework_ticket_id | string|null | The no-charge rework ticket to link; null clears the link |
curl -X PATCH "https://app.benchkey.com/api/v1/warranty_claims/27" \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" \ -H "Content-Type: application/json" \ -d '{ "status": "approved", "rework_ticket_id": "TK-10113" }'Node.js
Section titled “Node.js”const res = await fetch( "https://app.benchkey.com/api/v1/warranty_claims/27", { method: "PATCH", headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa", "Content-Type": "application/json", }, body: JSON.stringify({ status: "approved", rework_ticket_id: "TK-10113" }), });const claim = await res.json();Response
Section titled “Response”Returns the updated warranty claim object.
Error codes
Section titled “Error codes”| HTTP status | Code | Meaning |
|---|---|---|
400 | invalid_query | A list filter parameter was supplied as an array or object instead of a single scalar value, an unrecognized status filter, or /active was called with zero or multiple lookup parameters (“Provide exactly one of: ticket_id, customer, phone”) |
400 | invalid_cursor | The pagination cursor is malformed |
400 | invalid_body | Request body is not a JSON object |
400 | unknown_field | Body contains a field this endpoint doesn’t accept |
400 | missing_field | ticket_id is absent on create |
400 | invalid_field | A field value is invalid — e.g. a non-string reason, reason/resolution_notes over 1000 characters, or an unrecognized status value |
404 | not_found | No claim with that ID, or the referenced ticket does not exist for this tenant |
409 | conflict | The ticket has no active warranty, already has an open/approved claim, the status transition is illegal, or the rework ticket is already linked to another claim |
422 | create_failed | The claim could not be created |
403 | insufficient_scope | API key lacks warranty.read or warranty.write |
See Errors for the full error envelope format.