Changelog
Every change a client can see, newest first. Machines can read the same list at changelog.json.
Pricing from a product link, and replacement searches from MCP
- GET /api/v1/claims and the MCP tool list_claims filter by claimNumber (the whole number, not part of one), the number people usually call a claim by.
- New POST /api/v1/items/{itemId}/price-from-link and MCP tool price_from_link (items:write, Idempotency-Key / idempotencyKey): pricing from a retailer's product page, as pasting a link in the app does. The page's product name, model, store, link and price become the item's; a page with no price changes nothing on an item that already has a price (priced false; an unpriced item still gets the page's name, store and link). priceMethod search means the page could not be read and the price came from the same store's shopping listing (live keys only). With approve: true the item is approved too, only when the page itself priced it (approveSkipped otherwise: unpriced, price_via_search for a search price, which a person checks before approving, or not_approvable). A link that is not a public https page is a 400 parameter_invalid on url. 20 lookups a minute per credential.
- New MCP tool search_replacements (items:write, takes an idempotencyKey): runs the replacement finder again for one item. It waits up to about 20 seconds and returns status completed with the new offers and the item, or searching (poll get_replacements) or failed. Approved items are refused (item_already_approved); the finder's pick is never accepted for you. Limited to 5 a minute per credential and 3 a minute and 200 a day per organization (separately for test and live keys). Test keys get three fixture offers and no real search.
- GET /api/v1/items/{itemId}/replacements and get_replacements gain searching: true while a search for the item is running.
MCP photo tools: upload links, presigned uploads, looking at photos, and extra photos for an item
- New MCP tool get_upload_link (claims:read): a link that opens the claim in the app with its Add photos dialog, for a person to upload from their own device. Test claims are not shown in the app, so a test key gets a test_claim_not_in_app error.
- New MCP tools create_photo_upload and complete_photo_upload (photos:write, take an idempotencyKey), matching POST .../photo-uploads and .../photo-uploads/complete, for clients that can make HTTP PUT requests. The PUT URLs last 5 minutes; a retry with the same key returns the first URLs, so once they expire call create_photo_upload again with a new key.
- New MCP tools list_photos (photos:read, 25 a page by default) and get_photo (photos:read), which returns the photo and its image as an MCP image block: a WebP copy up to 1920 px (size medium, the default; the 400 px thumbnail when that copy is over 750 KB) or the thumbnail (size thumbnail). Originals are never sent. A photo with no preview yet returns a note instead of an image. get_photo images have their own budget of 60 a minute per credential.
- New MCP tools create_item_photo_upload and attach_item_photos (photos:write and items:write, take an idempotencyKey): add up to 10 new photos to an existing item, or link photos already on the claim, without analysis, so no duplicate item is drafted and nothing is billed. A photo from a claim photo upload that has not been completed cannot be attached (photo_not_attachable).
- GET /api/v1/claims/{claimId} and get_claim_status: analysis gains photosAttached, the photos added to an existing item as evidence (also when added in the app). They were counted in photosQueued, which kept analysis.status at in_progress for good; they are no longer queued. Such a photo's analysisStatus is now not_analyzed instead of queued.
Claim edits, item categories, and MCP tools for rooms, items, categories and the credential
- PATCH /api/v1/claims/{claimId} (claims:write) changes externalRef, claimNumber, insuredName, lossAddress, lossType, dateOfLoss, insuranceCompany and policyNumber; at least one field, null clears one. Status, valuation and sales tax are not editable there.
- GET /api/v1/claims/{claimId}/categories (items:read) lists the categories items on the claim can take, from the claim's taxonomy (jmidg by name, or xactimate with 3-letter codes), with each one's default depreciation.
- PATCH /api/v1/items/{itemId} and update_item take category: a name from that list, or a code on xactimate claims; null clears it, and an unknown one is a 400 parameter_invalid. Setting it on an xactimate claim resets the item's selector, as in the app.
- dateOfLoss before 1000-01-01 is now a 400 on POST /api/v1/claims as well (it was a server error).
- New MCP tools list_rooms (claims:read), get_item (items:read), list_categories (items:read), update_claim (claims:write, takes an idempotencyKey) and get_me (no scope needed), matching GET .../rooms, GET /api/v1/items/{itemId}, GET .../categories, PATCH /api/v1/claims/{claimId} and GET /api/v1/me.
MCP: smaller results, waiting on analysis, output schemas and prompts
- MCP tool results are compact JSON (no indentation) in the text block, alongside the same value as structuredContent, so large results fit assistants' tool-result limits.
- get_inventory now returns 50 items a page by default (was 100). Send limit (up to 100) for bigger pages, and follow nextCursor as before.
- get_claim_status takes waitSeconds (0-20, default 0): while analysis.status is in_progress the call waits up to that long for it to finish before answering, instead of the assistant polling.
- The read tools (list_claims, get_claim_status, get_inventory, get_replacements) declare an outputSchema, also published in mcp.json. Tools carry idempotentHint and openWorldHint annotations (add_photos is open-world: it fetches the URLs it is given).
- Three MCP prompts: review_claim, price_unpriced_items and add_photos_to_claim, listed in mcp.json. They are instructions only; the tools they call need their usual scopes.
Test-mode pipeline webhooks, the rest of the MCP review tools, OAuth app approval
- An OAuth app registered in Settings needs Contents.team approval before its tokens work, as a live API key does: until then they return 403 oauth_app_pending_approval. Apps that register themselves through dynamic client registration (an assistant connecting to the MCP server) are unaffected.
- Test endpoints now receive photos.analysis_completed, items.priced and export.ready for test claims (livemode: false), so a test key can run the whole flow end to end.
- New MCP tools add_item, delete_item, unapprove_items and reject_items, matching POST /api/v1/claims/{claimId}/items, DELETE /api/v1/items/{itemId} and POST .../items/unapprove and .../items/reject. Each needs items:write and takes an idempotencyKey; add_item requires one, so a retried add never creates (and bills) a second item.
- The API reference is now rendered by Contents.team from the same OpenAPI document, with a curl example for every endpoint.
Review and approve items through the API and MCP
- New scope items:write: edit, add, delete, approve and reject items. It does not include items:read.
- PATCH /api/v1/items/{itemId} edits name, model, quantity, unitCostCents, priceSource, priceSourceUrl, roomId, condition, estimatedAgeYears and notes, with the app's validation and price caps. An item being priced is a 409 item_locked.
- POST /api/v1/claims/{claimId}/items/approve approves up to 1000 items and reports each id as approved, alreadyApproved, locked, skipped (with a reason such as unpriced) or notFound. POST .../items/unapprove and POST .../items/reject (up to 100) do the reverse.
- POST /api/v1/claims/{claimId}/items adds an item by hand (approved on creation, as in the app); DELETE /api/v1/items/{itemId} removes one.
- GET /api/v1/items/{itemId}/replacements lists the replacement finder's offers (rpl_ ids); POST /api/v1/items/{itemId}/replacements/{replacementId}/accept prices the item from one and approves it.
- Items have priced and needsReview fields, and GET /api/v1/claims/{claimId}/items takes ?needsReview= and ?priced=.
- inventory.approved is also sent when a replacement offer is accepted, in the app or through the API.
- API approvals are metered exactly like approvals in the app; test claims are never billed.
- MCP: get_replacements, update_item, approve_items and accept_replacement; get_inventory takes needsReview and priced.
- New guide: Review and approve.
MCP: idempotencyKey on write tools
- create_claim, add_photos and export_report take an optional idempotencyKey argument (the Idempotency-Key rules: 1-255 visible ASCII characters, 24 hours). A retry with the same key and arguments returns the first result instead of acting twice; the same key with different arguments is an idempotency_key_reused tool error.
API v1: keys, claims and the developer portal
- Org API keys: owners and admins create them in Settings -> Connections -> API keys. ctk_test_ keys for test mode, ctk_live_ keys for live data; each key carries scopes.
- GET /api/v1/me returns the calling key, its scopes and its organization.
- GET /api/v1/claims lists claims newest first, with cursor pagination and externalRef and updatedSince filters.
- Claims have an externalRef field for your own id.
- The OpenAPI 3.1 document is public at /api/v1/openapi.json and /openapi/v1.yaml.
- developers.contents.team: guides, the API reference, llms.txt, changelog.json and mcp.json.
- The MCP server at https://contents.team/api/mcp (Streamable HTTP, stateless): list_claims, create_claim, add_photos, get_claim_status, get_inventory and export_report, authenticated with an API key or OAuth access token.
Breaking changes ship as a new API version and are announced here before they do.