Skip to content

Threads API guide

A Thread is the digital record for one physical item — an asset, part, document, or workflow item. It carries a name and description, typed field data, attached files, bound identifiers, and an event history. Threads are owned by a Team, so every request needs a bearer token plus the Dust-Ctx-Org-Id header (and Dust-Ctx-Team-Id to act as a specific Team) — see Authentication and Conventions.

This guide covers the main flows. For every parameter and response schema, see the API reference.

Operation Method & path
Create one or many Threads POST /api/v1/threads
List / search Threads GET /api/v1/threads
Count Threads GET /api/v1/threads/count
Get one Thread GET /api/v1/threads/{thread_id}
Update metadata and fields POST /api/v1/threads/{thread_id}
Update fields only POST /api/v1/threads/{thread_id}/data
List archived field data GET /api/v1/threads/{thread_id}/data/archived
Restore archived field data POST /api/v1/threads/{thread_id}/data/restore
Archive Threads PATCH /api/v1/threads/archive
Restore Threads PATCH /api/v1/threads/restore
Check caller permissions POST /api/v1/threads/permissions
Presence heartbeat POST /api/v1/threads/{thread_id}/presence
List a Thread’s files GET /api/v1/threads/{thread_id}/files
Set / upload thumbnail PATCH / POST /api/v1/threads/{thread_id}/thumbnail

POST /api/v1/threads accepts three body shapes, selected by type: single (one Thread), list (many normalized Threads), and raw (flat key-value records). All three accept an optional bundleId to create the Threads inside a Folder.

Terminal window
curl -fsS "$APID_URL/api/v1/threads" \
-H "Authorization: Bearer $DUST_TOKEN" \
-H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \
-H "Content-Type: application/json" \
-d '{
"type": "single",
"thread": { "name": "Tire SZ3J-11-ZJ17" },
"data": [
{ "name": "Serial Number", "type": "text", "value": { "text": "SZ3J-11-ZJ17" } },
{ "name": "Max PSI", "type": "number", "value": { "number": 51 } }
]
}'

Field values are nested under value by type — { "text": … }, { "number": … }, and so on. The spec defines inputs for text, long text, number, boolean, date, date range, date-time, time, duration, email, phone, URL, JSON, select, select-many, tags, resource (file) references, and thread references.

Use type: "list" when you already have normalized { thread, data } objects, or type: "raw" to hand the API flat records — it derives fields from each object’s key-value pairs, using nameKey and descriptionKey (default name / description) for the Thread’s own metadata:

{
"type": "raw",
"nameKey": "serial",
"raw": [
{ "serial": "SZ3J-11-ZJ17", "part": "P355/30R19", "maxPsi": 51 }
]
}

For importing whole assembly structures atomically, see POST /api/v1/imports/plan and POST /api/v1/imports/commit in the reference.

GET /api/v1/threads/{thread_id} returns the Thread with its field data (an optional maxEvents query includes recent events). GET /api/v1/threads lists with cursor pagination (cursor, pageSize, order, orderCol) and supports filters including:

Filter Meaning
q, queryCol Text search, optionally restricted to one column
bundleId Threads in a Folder or Category
templateId Threads created from a Template
tagType Threads with an identifier of this type bound
hasResources Threads with attached files
includeArchived, archivedOnly Archive visibility
createdBy, ownedByTeam Provenance filters
excludeTransferred, transferredOnly Shipped-away Threads
withActiveShipment Annotate each item with its active Shipment, if any

GET /api/v1/threads/count takes the same filters and returns only the count — useful for dashboards and pagination summaries.

Two endpoints, one intent split:

  • POST /api/v1/threads/{thread_id} — takes { thread, update?, remove? }: Thread metadata (name, description, template, …) plus optional field changes in one call.
  • POST /api/v1/threads/{thread_id}/data — fields only: { threadId, update, remove?, expectedUpdatedAt? }. Fields in update are upserted (matched by name/ID); remove takes field IDs.
POST /api/v1/threads/{thread_id}/data
{
"threadId": "9f6a…",
"update": [
{ "name": "VIN", "type": "text", "value": { "text": "1HGCM82633A004352" } }
],
"remove": []
}

Removing a field archives it rather than destroying it. GET /api/v1/threads/{thread_id}/data/archived lists archived fields, and POST /api/v1/threads/{thread_id}/data/restore brings them back by ID ({ threadId, restore: ["field-id", …] }).

Archiving is bulk and reversible:

  • PATCH /api/v1/threads/archive{ threadIds: […], toggle? }. With toggle: true, archived Threads in the list are unarchived and active ones archived in a single call.
  • PATCH /api/v1/threads/restore — restore archived Threads.

Archived Threads disappear from default listings; use includeArchived or archivedOnly to see them.

Before rendering edit controls or attempting writes across many Threads, ask what the caller can actually do:

Terminal window
curl -fsS "$APID_URL/api/v1/threads/permissions" \
-H "Authorization: Bearer $DUST_TOKEN" \
-H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \
-H "Content-Type: application/json" \
-d '{ "threadIds": ["9f6a…", "c2d1…"] }'

POST /api/v1/threads/permissions returns the caller’s effective permissions per Thread in the current Team context. Related reads: GET /api/v1/threads/{thread_id}/access (which Teams provide access) and GET /api/v1/threads/{thread_id}/shared (who the Thread is shared with) — both covered in Teams, sharing, and connections.

POST /api/v1/threads/{thread_id}/presence is a heartbeat: send it periodically while a user views a Thread (optionally with display name / image, and leaving: true on exit) and the response lists the Thread’s current viewers. DICE uses this for the “who else is here” indicator.

Files attach to Threads through the Files API; the Thread-side reads live here:

  • GET /api/v1/threads/{thread_id}/files — the Thread’s files, cursor-paginated (includeArchived is required).
  • GET /api/v1/threads/{thread_id}/files/{res_id} / POST …/files/{res_id} — read and update a single attached file.
  • POST /api/v1/threads/{thread_id}/thumbnail — upload an image (multipart, thumbnail field) and set it as the Thread’s thumbnail in one step.
  • PATCH /api/v1/threads/{thread_id}/thumbnail — set the thumbnail from an existing resource ID or an image URI.