API Reference
Base URL: https://app.dayofplenty.com/api/v1
Auth: Bearer token — generate from Settings → API Keys.
Authentication
Section titled “Authentication”All requests require a Bearer token in the Authorization header:
curl -s -H "Authorization: Bearer pw_..." https://app.dayofplenty.com/api/v1/accountAPI keys are created in the app under Settings → API Keys. The token is shown once — save it immediately.
Endpoints
Section titled “Endpoints”| Resource | List | Create | Get | Update | Archive | Restore |
|---|---|---|---|---|---|---|
| Account | — | — | GET /account | PATCH /account | — | — |
| Things | GET /things | POST /things | GET /things/:id | PATCH /things/:id | PATCH .../archive | PATCH .../restore |
| Thing types | GET /things/types | POST /things/types | GET /things/types/:id | PATCH /things/types/:id | PATCH .../archive | PATCH .../restore |
| Labels | GET /labels | POST /labels | GET /labels/:id | PATCH /labels/:id | PATCH .../archive | PATCH .../restore |
| Workflows | GET /workflows | POST /workflows | GET /workflows/:id | PATCH /workflows/:id | PATCH .../archive | PATCH .../restore |
| Requirements | GET /workflows/:id/requirements | POST /workflows/:id/requirements | GET .../requirements/:id | PATCH .../requirements/:id | PATCH .../archive | PATCH .../restore |
| Users | GET /users | POST /users | GET /users/:id | PATCH /users/:id | PATCH .../archive | PATCH .../restore |
| Events | GET /events | — | GET /events/:id | — | — | — |
Common patterns
Section titled “Common patterns”Create a workflow + requirement
Section titled “Create a workflow + requirement”BASE="https://app.dayofplenty.com/api/v1"AUTH="Authorization: Bearer ***"
# Create a workflowASGN=$(curl -s -H "$AUTH" -H "Content-Type: application/json" \ -d '{"name":"Night Clean"}' $BASE/workflows)ASGN_ID=$(echo $ASGN | jq -r '.id')
# Add a requirement to the workflowcurl -s -H "$AUTH" -H "Content-Type: application/json" \ -d '{"name":"Restroom Check","requirement_type":"select_option","config":{"choices":["8F","6F","4F"]}}' \ $BASE/workflows/$ASGN_ID/requirementsFilter events
Section titled “Filter events”curl -s -H "$AUTH" "$BASE/events?type=submission&from=2026-07-01T00:00:00Z&limit=50"Things and thing types
Section titled “Things and thing types”Every thing belongs to exactly one thing type, an account-declared kind of thing — “Gate”, “Ingredient”, “Cement” — managed on the Things surface at /things/types. A type carries tracked_by (quantity or state); a quantity type also carries its unit, and a state type its declared states. Types archive rather than delete, because things, requirements and rule actions reference them.
Address a thing by its numeric id. The id is an integer — anything else returns 404.
POST /things fields:
| Field | Notes |
|---|---|
name | Required. |
thing_type_id | Required. Must be one of your account’s active types. |
code_value | Optional; a value is generated when omitted. |
details | Optional object. |
label_ids | Optional array of label ids from your account. |
PATCH /things/:id accepts name, details, label_ids, opening_quantity and opening_state. The thing’s type cannot be changed after creation.
curl -s -H "$AUTH" -H "Content-Type: application/json" \ -d '{"name":"North Gate","thing_type_id":7,"code_value":"GATE-001"}' $BASE/thingsA thing response includes id, name, code_value, thing_type_id, thing_type (the type’s name), tracked_by, unit, details, labels, archived_at, created_at and updated_at. GET /things/:id and POST /things also return qr_code and verify_token.
Thing types
Section titled “Thing types”Manage your account’s kinds of thing — including any type with no things yet:
| Endpoint | Does |
|---|---|
GET /things/types | List the active types. |
POST /things/types | Create one. name and tracked_by are required, plus unit for quantity or states for state. |
GET /things/types/:id | Fetch one. |
PATCH /things/types/:id | Rename, or switch the axis. Switching tracked_by clears the field that no longer applies. |
PATCH /things/types/:id/archive | Archive. |
PATCH /things/types/:id/restore | Restore. |
Rename a type to “Ingredients” — take the id from thing_type_id on any thing, or from the list:
curl -s -H "$AUTH" -H "Content-Type: application/json" \ -X PATCH -d '{"name":"Ingredients"}' $BASE/things/types/7A type response includes id, name, tracked_by, unit, states, position, archived_at, created_at and updated_at.
Labels
Section titled “Labels”There is no DELETE for a label — archive it. Attaching and detaching live on the thing.
| Endpoint | Does |
|---|---|
GET /labels | List labels. |
POST /labels | Create one. name is required, color is optional. |
GET /labels/:id | Fetch one. |
PATCH /labels/:id | Rename or recolour (name, color). |
PATCH /labels/:id/archive | Archive. |
PATCH /labels/:id/restore | Restore. |
Set a thing’s labels with label_ids; an empty array clears them:
curl -s -H "$AUTH" -H "Content-Type: application/json" \ -X PATCH -d '{"label_ids":[]}' $BASE/things/12Create a worker user
Section titled “Create a worker user”curl -s -H "$AUTH" -H "Content-Type: application/json" \ -d '{"name":"Naseer","phone":"0820000003","pin":"5678","role":"worker"}' $BASE/usersResponse format
Section titled “Response format”All endpoints return JSON. Errors follow a consistent format:
{"error": "not found"}List endpoints return only active (non-archived) resources by default — GET /labels is the exception and returns archived labels too. Use archive/restore endpoints to manage lifecycle.
Full OpenAPI spec
Section titled “Full OpenAPI spec”The canonical reference is the OpenAPI 3.0.3 spec:
- Live spec:
GET /docs/openapion the app - Interactive docs: Scalar UI on the app
Import the spec into Postman, use with codegen tools, or feed to your AI agent.