Quickstart
Create an API key
Owners and admins create keys in Contents.team under Settings → Connections → API keys. Choose Test mode, give the key a name, and tick the scopes this walkthrough uses: claims:read, claims:write, photos:write and items:read. The key is shown once; keep it in an environment variable, never in source control.
export CONTENTS_API_KEY="ctk_test_..."Check it works. /api/v1/me needs no scope and tells you which organization and mode the key belongs to.
curl https://contents.team/api/v1/me \
-H "Authorization: Bearer $CONTENTS_API_KEY"{
"object": "me",
"organization": {
"id": "org_11oWFaVHi",
"name": "Larkin Restoration"
},
"mode": "test",
"credential": {
"type": "api_key",
"name": "Job sync (staging)",
"prefix": "ctk_test_Qm4r",
"scopes": [
"claims:read",
"claims:write",
"photos:write",
"items:read"
],
"createdAt": "2026-11-01T14:00:00.000Z",
"lastUsedAt": "2026-11-01T14:05:31.000Z",
"expiresAt": null
}
}List your claims
Claims come back newest first, 25 to a page. Pass nextCursor as cursor to get the next page, and externalRef to find the claim you created for one of your own records.
curl "https://contents.team/api/v1/claims?limit=1" \
-H "Authorization: Bearer $CONTENTS_API_KEY"{
"object": "list",
"data": [
{
"id": "clm_0a6NnX3I9",
"object": "claim",
"mode": "live",
"externalRef": "JOB-1042",
"claimNumber": "HO-2026-118342",
"insuredName": "Dana Whitfield",
"lossAddress": "1418 Larkin St, Denver, CO 80211",
"lossType": "Water",
"dateOfLoss": "2026-10-19",
"status": "in_progress",
"insuranceCompany": "Front Range Mutual",
"policyNumber": "FRM-HO3-7720931",
"valuationMode": "rcv",
"salesTaxBp": 881,
"itemCount": 64,
"approvedRcvCents": 1874215,
"createdAt": "2026-10-21T15:02:11.000Z",
"updatedAt": "2026-10-24T18:40:52.000Z"
}
],
"hasMore": true,
"nextCursor": "clm_0a6NnX3I9"
}Ids are opaque strings with a type prefix (clm_ for a claim), money is integer cents (approvedRcvCents) and rates are basis points (salesTaxBp, 881 = 8.81%).
Create a claim
Send your own id as externalRef and an Idempotency-Key, so a retried request returns the same claim instead of making a second one.
curl https://contents.team/api/v1/claims \
-H "Authorization: Bearer $CONTENTS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: job-1042-create" \
-d '{
"externalRef": "JOB-1042",
"insuredName": "Dana Whitfield",
"lossAddress": "1418 Larkin St, Denver, CO 80211",
"lossType": "Water",
"dateOfLoss": "2026-10-19"
}'The response is the claim, with its clm_ id. The examples below use clm_0a6NnX3I9.
Add photos
Pass up to 10 publicly reachable https photo URLs per call (a signed link from your storage is fine), each with an optional roomName (the room is created if the claim has none by that name) and your own externalId. Contents.team fetches each photo, analyzes it and drafts its visible items. In test mode the photos are not analyzed; you get a fixed set of items back within seconds. For files you hold yourself, use POST /api/v1/claims/{claimId}/photo-uploads to get presigned upload URLs instead.
curl https://contents.team/api/v1/claims/clm_0a6NnX3I9/photos \
-H "Authorization: Bearer $CONTENTS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: job-1042-photos-1" \
-d '{
"photos": [
{
"url": "https://files.example.com/jobs/1042/living-room-1.jpg",
"roomName": "Living room",
"externalId": "IMG-0001"
},
{
"url": "https://files.example.com/jobs/1042/living-room-2.jpg",
"roomName": "Living room",
"externalId": "IMG-0002"
}
]
}'Wait for pricing
Two ways to know the inventory is ready:
- Webhooks (recommended): register an endpoint and receive
photos.analysis_completed, thenitems.priced. See Webhooks. - Polling: list claims with
updatedSince, or read the claim's items every 30 seconds or so. Stay well inside the rate limit of 300 requests a minute per key.
Read the inventory
Each item is one line: what it is, the room it was found in, its condition, the replacement price with its source, depreciation and the resulting RCV and ACV. Items start pending and become approved when someone in your organization reviews them, in Contents.team or in your own product through the API: see Review and approve. needsReview and priced on each item say what still needs a person.
curl "https://contents.team/api/v1/claims/clm_0a6NnX3I9/items?limit=100" \
-H "Authorization: Bearer $CONTENTS_API_KEY"{
"id": "itm_0EXaAMAJl",
"object": "item",
"claimId": "clm_0a6NnX3I9",
"roomId": "rom_0V2hfb6gd",
"roomName": "Living room",
"name": "Samsung 65\" QLED 4K Smart TV (QN65Q80C)",
"description": "65 inch flat-screen television",
"retailerDescription": "Samsung 65\" QLED 4K Smart TV (QN65Q80C)",
"model": "QN65Q80C",
"category": "Electronics",
"quantity": 1,
"unitCostCents": 129999,
"priced": true,
"status": "approved",
"needsReview": false,
"condition": "Average",
"estimatedAgeYears": 2,
"source": "ai",
"priceSource": "Best Buy",
"priceSourceUrl": "https://www.bestbuy.com/site/6536963.p",
"notes": null,
"photoIds": [
"pho_0TKGshODY"
],
"valuation": {
"subtotalCents": 129999,
"taxCents": 11453,
"rcvCents": 141452,
"depreciationBp": 2000,
"depreciationCents": 28290,
"acvCents": 113162,
"paymentCents": 113162
},
"createdAt": "2026-10-21T15:20:44.000Z",
"updatedAt": "2026-10-24T18:40:52.000Z"
}Go live
When the flow works with a test key, create a live key the same way. Test keys are self-serve; live keys need approval from Contents.team, usually after a partner agreement and DPA. A new live key is shown once as usual, and we get the request automatically, but until it is approved every call with it returns 403 with the code live_key_pending_approval. Settings shows the key as Pending approval until then. Write to integrations@contents.team to move it along.
Live keys act on real claims; approved items count toward the organization's plan exactly as they do in the app, and the API adds no charge of its own.