STUFFOWL / DEVELOPERS

API guide

The base URL is https://stuffowl.com/api/v1. Send a bearer token on every private request, including image downloads.

1. Find the records you need

List unnamed photographed items

curl --fail-with-body \
  -H "Authorization: Bearer $STUFFOWL_TOKEN" \
  'https://stuffowl.com/api/v1/nodes?kind=item&unnamed=true&hasPhoto=true&limit=25'

Response shape

{
  "nodes": [{
    "id": "00000000-0000-4000-8000-000000000123",
    "shortCode": "I-023",
    "name": "",
    "revision": "<current revision>",
    "coverAttachmentId": "<attachment UUID>"
  }],
  "nextCursor": null
}

This abbreviated example omits other record fields. For additional pages, resend the same filters with cursor=nextCursor. Limits are 1–100, default 50. parentId=root selects top-level records. A null cursor means you reached the end.

2. Retrieve private photos

Read GET /nodes/{id}/attachments with inventory:read. Then use photos:read to retrieve an image:

curl --fail-with-body \
  -H "Authorization: Bearer $STUFFOWL_TOKEN" \
  "https://stuffowl.com/api/v1/attachments/$ATTACHMENT_ID/content" \
  --output item.jpg

A private URL by itself does not give an AI model access. Send authenticated image bytes to your chosen provider, or use MCP’s get_photo tool. Stored receipts may be PDFs; check Content-Type.

3. Preview, apply, and undo suggestions

Send a batch of up to 50 changes. The server captures current values without changing the records.

POST /enrichment/batches

{
  "title": "Name the workshop tools",
  "changes": [{
    "nodeId": "00000000-0000-4000-8000-000000000123",
    "patch": {
      "name": "Claw hammer",
      "description": "Wooden handle with a steel claw head"
    }
  }]
}

Review batch.changes, including before and patch. To approve the saved batch, call POST /enrichment/batches/{id}/apply with no body. To restore its original fields, call POST /enrichment/batches/{id}/undo.

A conflict changes nothing. If any record changes between preview and apply, or between apply and undo, the entire operation returns 409. Read the current records and create a fresh preview. Each batch can be applied once and undone once.

Enrichment supports name, description, brand, model, condition, and status. Use tags for categories such as “tools” or “kitchen”. Only suggest a brand or model when the photo provides reliable evidence.

Update one record without overwriting newer edits

PAT and OAuth integrations must read the record’s revision, then pass it in If-Match with a PATCH:

curl --fail-with-body -X PATCH \
  -H "Authorization: Bearer $STUFFOWL_TOKEN" \
  -H "Content-Type: application/json" \
  -H "If-Match: $REVISION" \
  --data '{"name":"Claw hammer","quantity":2}' \
  "https://stuffowl.com/api/v1/nodes/$NODE_ID"

Unspecified fields stay unchanged. Nullable fields accept null to clear them. Money uses integer cents; input dates use YYYY-MM-DD. Quantities are returned as decimal strings.

Create an item and attach a photo

Create a named record with POST /nodes, then upload an image using its returned UUID. This works well for scripts and imports.

POST /nodes

{"kind":"item","name":"Cordless drill","parentId":null}

Upload

curl --fail-with-body \
  -H "Authorization: Bearer $STUFFOWL_TOKEN" \
  -F 'kind=photo' -F '[email protected]' \
  "https://stuffowl.com/api/v1/nodes/$NODE_ID/attachments"

Uploads accept files up to 15 MB. Photos accept JPEG, PNG, WebP, HEIC, and HEIF; receipts also accept PDF. The server normalizes and compresses images and applies the inventory’s storage allowance.

Use the native capture workflow

The existing multipart POST /capture endpoint supports camera-first capture, destination resolution, and capture-session actions. Its intent-specific contract is maintained with the mobile workflow. For general integrations, the create-and-upload sequence above has fewer moving parts.

Handle errors and retries

Errors use {"error":"code","message":"optional explanation"}. Retry a 429 after the number of seconds in Retry-After. Read current state after a 409. A 404 covers both unknown IDs and records outside your inventory.

Creation, uploads, and physical print requests are not automatically deduplicated. After a network timeout, check inventory or print state before retrying. Listing is paginated; exports include a full subtree and may be large.

See all endpoints and error codes →