API Conventions · Developers
Conventions that hold across every Dailybot API endpoint: identifiers, timestamps, casing, pagination, search, date range, and versioning.
Every endpoint in the Dailybot public API follows the same conventions for identifiers, timestamps, field casing, pagination, search, date range, and versioning. Learn them once here and every reference page will read exactly as you expect.
Identifiers
Every resource has a globally unique UUID (RFC 4122 v4). Depending on the model, the API returns it as uuid (Form, Form Response, User) or as id (Kudo, Check-in, Workflow) — in both cases the value is a UUID and can be used as a stable, opaque key in your integration.
Rule of thumb: if a resource has a dedicated UUID column separate from its internal primary key, the API returns uuid; if the primary key itself is a UUID, the API returns id. Both are UUIDs.
| Resource | Identifier field |
|---|---|
| Form | uuid |
| Form Response | uuid |
| Agent Report | uuid (also returns id with the same value for backward compatibility) |
| Agent Message | uuid (also returns id with the same value for backward compatibility) |
| User | uuid |
| Kudo | id (UUID) |
| Check-in (Follow-up) | id (UUID) |
| Workflow | id (UUID) |
Timestamps
All timestamps are ISO-8601 in UTC with millisecond precision (e.g. 2026-07-02T14:33:19.412Z). Fields ending in _at are timestamps; fields ending in _date are date-only (YYYY-MM-DD). We never emit local-time strings.
Field casing
All JSON keys are snake_case (first_name, created_at). URL path segments are kebab-case (/pending-invitations/, /agent-reports/). Query parameters are snake_case (include_email, only_active).
Pagination
Every /v1/* list endpoint returns the same response envelope:
{
"count": 152,
"next": "https://api.dailybot.com/v1/...?page=2&page_size=50",
"previous": null,
"results": [ ... ]
}
Query parameters
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page |
integer | 1 | — | Page number (1-indexed) |
page_size |
integer | 25 | 100 | Items per page. Values > 100 are silently clamped. |
Legacy aliases (backwards-compatible)
| Legacy param | Maps to |
|---|---|
limit |
page_size |
offset |
Offset-based pagination |
These aliases return the same envelope. next/previous URLs echo whichever style the caller used.
Removed opt-in pagination: The
?paginated=truequery parameter and theX-Dailybot-Paginate: truerequest header are ignored. Every list endpoint always returns the envelope.
Response envelope fields
| Field | Type | Description |
|---|---|---|
count |
integer | Total items matching the query (across all pages) |
next |
string | null | Full URL of the next page, or null if this is the last page |
previous |
string | null | Full URL of the previous page, or null if this is the first page |
results |
array | Items for this page (always an array, never null) |
Paginated endpoints
| Endpoint | Default ordering |
|---|---|
GET /v1/forms/ |
-created_at (newest first) |
GET /v1/forms/{uuid}/responses/ |
-created_at |
GET /v1/checkins/ |
-created_at |
GET /v1/checkins/{uuid}/responses/ |
-created_at |
GET /v1/kudos/ |
-id |
GET /v1/kudos/organization/ |
-id |
GET /v1/kudos/wall-of-fame/ |
-count (top contributors) |
GET /v1/users/ |
full_name |
GET /v1/teams/ |
name |
GET /v1/workflows/ |
-created_at |
GET /v1/pending-invitations/ |
-created_at |
GET /v1/agent-messages/ |
-created_at |
Iterating all pages
PAGE=1
while true; do
RESP=$(curl -s "https://api.dailybot.com/v1/forms/?page=$PAGE&page_size=100" \
-H "X-API-KEY: $DAILYBOT_API_KEY")
echo "$RESP" | jq '.results[]'
NEXT=$(echo "$RESP" | jq -r '.next')
[ "$NEXT" = "null" ] && break
PAGE=$((PAGE + 1))
done
Search
A ?search=<term> parameter is available on list endpoints that expose text content. It performs a case-insensitive substring match applied after role scope — you can only search content you are already authorized to see. Composes with pagination and date-range filters.
Max query length: 256 characters. Over-length requests return 400 with code: "search_query_too_long".
Endpoints supporting search
| Endpoint | Fields searched |
|---|---|
GET /v1/forms/?search=<term> |
Form name |
GET /v1/checkins/?search=<term> |
Check-in name |
GET /v1/forms/{uuid}/responses/?search=<term> |
Response content |
GET /v1/checkins/{uuid}/responses/?search=<term> |
Response content |
GET /v1/kudos/?search=<term> |
Kudo message |
GET /v1/kudos/organization/?search=<term> |
Kudo message |
GET /v1/workflows/?search=<term> |
Workflow name |
GET /v1/followups/?search=<term> |
Check-in name (deprecated alias of /v1/checkins/) |
GET /v1/users/?search=<term> |
Full name, email |
curl "https://api.dailybot.com/v1/forms/?search=retro&page_size=10" \
-H "X-API-KEY: $DAILYBOT_API_KEY"
Date range
A timezone-aware date range filter is available on every paginated endpoint.
Canonical parameters
| Parameter | Format | Description |
|---|---|---|
start_date |
YYYY-MM-DD |
Inclusive start — 00:00:00 in caller’s timezone |
end_date |
YYYY-MM-DD |
Inclusive end — 23:59:59.999999 in caller’s timezone |
Timezone behavior: Dates are interpreted in the authenticated user’s timezone (from their profile). Falls back to UTC when no timezone is set.
Also accepted (legacy aliases)
| Legacy params | Equivalent |
|---|---|
date_start / date_end |
start_date / end_date |
date_from / date_to |
start_date / end_date |
Composition
Composes with ?search= and pagination:
curl "https://api.dailybot.com/v1/checkins/{uuid}/responses/?start_date=2026-07-01&end_date=2026-07-31&search=blocker&page_size=100" \
-H "X-API-KEY: $DAILYBOT_API_KEY"
Error: Malformed dates return 400 with code: "invalid_date_range".
Case-insensitive filters
Enum-style query parameters accept any casing. For example, ?filter=kudos_received, ?filter=KUDOS_RECEIVED, and ?filter=Kudos_Received all resolve to kudos_received. Invalid values return 400 with code: "invalid_kudos_filter".
Versioning
The public API is versioned by URL prefix (/v1/). Additive changes (new endpoints, new optional fields, new enum values that fall back to defaults) may land at any time. Breaking changes ship behind a new prefix (/v2/) with a minimum 6-month sunset window on the prior version. See /developers/api-changelog for the running log.
Idempotency
All GET, PATCH, DELETE requests are idempotent by HTTP semantics — retrying them is safe. POST requests that create a resource are, in the general case, not idempotent; a naive retry after a network blip can create duplicate resources. When you retry after a 5xx or network error, always re-read the resource by its natural key (email, name, external id) first and only re-create if the read returns 404. Retry policy details live at /developers/errors#retry-policy.
null vs. missing
A field set to null explicitly means “this attribute has no value”. A field that is absent from the response means “the caller does not have permission to see it” or “the field was not requested via an include-flag”. Do not treat the two identically.