# Dib Public API — integration brief for an AI assistant You are helping a developer integrate the Dib Public API into their project. Dib is an AI-powered home-management platform. The API exposes everything Dib knows about a home — inventory, vehicles, documents, tasks, rooms, and the home profile — over a REST API, an MCP server, and a change feed. Follow the rules below exactly; when unsure, fetch the discovery endpoints instead of guessing. ## Stability - The Dib API is in PUBLIC PREVIEW and may change during the preview period. Pin the "Dib-API-Version" header so you opt into a known snapshot, and watch https://dib.io/developers/changelog for breaking changes. ## Base URL & auth - Base URL: https://dib.io/api/v1 - Auth: send "Authorization: Bearer " on EVERY request. Keys start with dib_live_ (production) or dib_test_ (sandbox with fixture data). The API is a Pro feature. Never hardcode the secret — read it from an env var such as DIB_API_KEY. - Versioning: optionally pin behavior with "Dib-API-Version: 2026-06-01" (the current version). Omit it and you are auto-pinned to the version that was current when the key was created. The /v1 path itself never changes; only the dated header changes behavior. Responses echo the resolved Dib-API-Version. ## First call: verify the key - GET https://dib.io/api/v1/me -> returns the key's team, environment, granted scopes, plan, pinned + resolved API version, and per-minute rate limits. Requires a valid key but no scope. Call this FIRST to confirm the key works and to see which scopes you actually have before building anything. ## Discovery (no auth required) - GET https://dib.io/api/v1 -> root index: resources, conventions, links - GET https://dib.io/api/v1/_meta -> machine-readable scopes + error catalog - OpenAPI spec: https://dib.io/api/openapi/v1 If you are ever unsure about a field or endpoint, read one of these rather than guessing. ## Response envelopes (always JSON) - Success: { "data": , "meta": { "request_id": "req_..." } } - List: { "data": [ ... ], "meta": { "request_id": "req_...", "page": { "has_more": false, "next_cursor": "..." | null } } } - Error: { "error": { "type", "message", "fix", "doc_url", "details" }, "meta": { "request_id": "req_..." } } On a non-2xx response, branch on the HTTP status, then read error.type for programmatic handling and error.fix for a human-readable next step. ## List / query convention (shared by every collection) - limit default 50, max 100 - cursor opaque; paginate by passing meta.page.next_cursor back as ?cursor=. Stop when has_more is false. Never assume one page. - sort created_at (default) | updated_at - order asc | desc (default desc) - created_since ISO date/datetime filter on creation time - updated_since ISO date/datetime filter on update time; pair with sort=updated_at for incremental sync - fields comma-separated allowlist to trim the response - expand comma-separated relations to inline (e.g. expand=room on inventory) ## Field formats - date ISO calendar date, YYYY-MM-DD - timestamp ISO-8601 date or datetime (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ssZ) - money non-negative decimal string, e.g. "1999.99" - year 4-digit integer - count non-negative integer ## Writes - POST creates, PATCH updates (partial merge — send only the fields you want to change), DELETE removes (idempotent). - Send a unique "Idempotency-Key" header on every POST. Dib dedupes it for 24h and replays the original response on retry. - Bulk: POST /v1/{inventory|vehicles|documents|tasks|rooms}/bulk with a body of { "operations": [ { "method": "create|update|delete", ...fields } ] } (max 50 ops). Returns HTTP 207 with a per-operation result array. ## Resources & scopes (scope format: resource:action) - inventory inventory:read / inventory:write - vehicles vehicles:read / vehicles:write - documents documents:read / documents:write (attach via subject_type = home | inventory | vehicle + subject_id, or leave general) - tasks tasks:read / tasks:write - rooms rooms:read / rooms:write - property property:read / property:write (the home profile is a singleton: PATCH /v1/property upserts it, GET /v1/property returns data: null until set) - search search:read — GET /v1/search?q=<2+ chars>&types=inventory,vehicle,document,task,room - events events:read — change feed: poll GET /v1/events?cursor=... or open an SSE stream at GET /v1/events/stream - exports exports:write — trigger async export jobs Canonical resource-type vocabulary is SINGULAR everywhere: inventory | vehicle | document | task | room | property. ## Rate limits Per key: 300 reads/min, 60 writes/min, 20 bulk/min. Responses carry X-RateLimit-Limit / -Remaining / -Reset. A 429 includes Retry-After (seconds) — honor it; repeated 429s can flag the key as abusive. ## MCP server (for AI agents) Streamable HTTP MCP server at POST https://dib.io/api/mcp, authenticated with the same "Authorization: Bearer " header. A tool is callable only if the key carries the matching scope. Tools: dib_search, dib_list_inventory, dib_get_inventory_item, dib_create_inventory, dib_list_vehicles, dib_get_vehicle, dib_create_vehicle, dib_list_tasks, dib_create_task, dib_update_task, dib_list_documents, dib_get_document, dib_create_document, dib_list_rooms, dib_get_property, dib_update_property. ## Minimal request curl -s "https://dib.io/api/v1/inventory?limit=5" \ -H "Authorization: Bearer $DIB_API_KEY" \ -H "Dib-API-Version: 2026-06-01" ## Rules for you, the assistant 0. Start by calling GET /v1/me to verify the key and confirm its scopes. 1. Send Authorization on every call; read the key from an env var, never inline. 2. Add a unique Idempotency-Key header to every POST. 3. Paginate with meta.page.next_cursor; stop when has_more is false. 4. On non-2xx, inspect error.type and error.fix instead of retrying blindly. 5. For syncs, use sort=updated_at with updated_since (or the /v1/events feed). 6. Use the singular resource-type vocabulary and the documented field formats. 7. When a field or endpoint is unclear, GET https://dib.io/api/v1 or the OpenAPI spec at https://dib.io/api/openapi/v1 before guessing.