# API conventions

> Conventions that hold across every Dailybot API endpoint: identifiers, timestamps, casing, pagination, search, date range, and versioning.

Language: en
Canonical: https://www.dailybot.com/developers/conventions
Markdown: send header `Accept: text/markdown` on any URL to receive Markdown instead of HTML.
Last Updated: 2026-07-10

---

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.

<h2 id="identifiers">Identifiers</h2>

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) |

<h2 id="timestamps">Timestamps</h2>

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.

<h2 id="casing">Field casing</h2>

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`).

<h2 id="pagination">Pagination</h2>

Every `/v1/*` list endpoint returns the same response envelope:

```json
{
  "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=true` query parameter and the `X-Dailybot-Paginate: true` request 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

```bash
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
```

<h2 id="search">Search</h2>

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 |

```bash
curl "https://api.dailybot.com/v1/forms/?search=retro&page_size=10" \
  -H "X-API-KEY: $DAILYBOT_API_KEY"
```

<h2 id="date-range">Date range</h2>

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:

```bash
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"`.

<h2 id="case-insensitive-filters">Case-insensitive filters</h2>

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"`.

<h2 id="versioning">Versioning</h2>

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](/developers/api-changelog) for the running log.

<h2 id="idempotency">Idempotency</h2>

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](/developers/errors#retry-policy).

<h2 id="null-vs-missing">null vs. missing</h2>

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.

---

## Developer portal navigation

**Getting Started**

- [Overview](/developers)
- [Quick start](/developers/getting-started)
- [Authentication](/developers/authentication)

**API Reference**

- [API Overview](/developers/api)
- [Users](/developers/api/users)
- [Organization](/developers/api/organization)
- [Teams](/developers/api/teams)
- [Invitations](/developers/api/invitations)
- [Check-ins](/developers/api/check-ins)
- [Forms](/developers/api/forms)
- [Report channels](/developers/api/report-channels)
- [Templates](/developers/api/templates)
- [Kudos](/developers/api/kudos)
- [Mood tracking](/developers/api/mood)
- [Important dates](/developers/api/important-dates)
- [Messaging](/developers/api/messaging)
- [Automations](/developers/api/workflows)
- [Webhooks](/developers/api/webhooks)
- [Commands platform](/developers/api/commands-platform)
- [Agents](/developers/api/agents)
- [OAuth2](/developers/api/oauth2)
- [Integrations](/developers/api/integrations)
- [CLI](/developers/api/cli)

**API guides**

- [Errors & Status Codes](/developers/errors)
- [Rate Limits](/developers/rate-limits)
- [Conventions](/developers/conventions) (this page)
- [API Changelog](/developers/api-changelog)
- [Recipes](/developers/recipes)

**Developer Features**

- [Custom commands](/developers/custom-commands)
- [Serverless commands](/developers/serverless)
- [Webhooks & events](/developers/webhooks)
- [Automation API trigger](/developers/workflow-trigger)
- [Activity API](/developers/activity-api)

**CLI**

- [Overview](/developers/cli)
- [Authentication](/developers/cli-authentication)
- [Command reference](/developers/cli-reference)
- [CI/CD recipes](/developers/cli-ci-cd)
- [Configuration](/developers/cli-configuration)
- [Troubleshooting](/developers/cli-troubleshooting)

**Agent Skill**

- [Overview](/developers/agent-skill)
- [Skills catalog](/skills)

---

## Site navigation

**Product:**
- [Home](/)
- [Product](/product)
- [Pricing](/pricing)
- [Enterprise](/enterprise)
- [Integrations](/integrations)
- [Templates](/templates)

**Resources:**
- [Blog](/blog)
- [Academy](/academy)
- [Changelog](/changelog)
- [Help Center](/help)
- [Developers](/developers)
- [Agents](/agents)

**Company:**
- [About](/about)
- [Careers](/careers)
- [Security](/security)
- [Contact Sales](/demo)

**Connect:**
- [LinkedIn](https://www.linkedin.com/company/dailybot/)
- [X/Twitter](https://twitter.com/dailybot)
- [GitHub](https://github.com/Dailybot-Inc)
- [YouTube](https://www.youtube.com/channel/UC3uM9V52vwX7e3vQpCc4qvA)

