Patterns & Conventions
A handful of conventions and patterns that make working with the Steady API smoother. For exact field names and schemas, the OpenAPI specification is always the source of truth — it updates automatically whenever the API changes, so prefer fetching it live over working from memory.
Conventions across the API
These hold consistently across endpoints:
- IDs are UUIDs (strings).
- Dates use ISO formats:
datefields areYYYY-MM-DD;*_atfields are ISO 8601 datetimes like2026-05-04T18:18:22Z. - Long-form text fields such as
previous,intentions,blockers, and commentbodyare Markdown. Use@usernameto mention people — Steady links these automatically. - Pagination on list endpoints uses
page(1-indexed) andper_page. - Array query parameters use the repeated
name[]=valueform, e.g.people_ids[]=abc&people_ids[]=def— not comma-separated. - Date-range filtering uses
sinceanduntilon most list endpoints, both inclusive.
Check-ins are PATCH-only
Check-ins are the one resource that doesn’t follow standard CRUD, and it surprises most people:
There is no create endpoint for check-ins. Steady pre-generates them from each team’s check-in schedule and the assigned person’s absences. To fill one out, you find the existing record and PATCH it.
The workflow is find-then-update. List check-ins to locate the record, filtering by person and date range:
GET /check-ins?since=2026-05-04&until=2026-05-04&people_ids[]={person_id}
Take the id off the returned record and PATCH it with the answer fields:
PATCH /check-ins/{id}
Content-Type: application/json
{
"previous": "- Shipped X\n- Reviewed Y\n",
"intentions": "- Roll X to prod\n",
"blockers": "",
"mood": "focused",
"previous_completed": true
}
If GET /check-ins returns nothing for a date, the person is absent or their team isn’t scheduled to check in that day — that’s expected, not an error. mood is a fixed enum; check the spec for the current values.
This is unique to check-ins. Most other resources — goals, goal updates, comments, reactions, echo answers — behave like normal REST, with POST to create and PATCH to update.
Common patterns
These are the workflows people reach for most often. Most patterns that involve “me” or “my” start by resolving the authenticated person’s UUID — that’s the first pattern below. Confirm exact field names against the spec as you build.
Get your person ID
GET /me returns the authenticated person. Grab .id and reuse it for any filter that needs your UUID — the API doesn’t accept a literal "me" or "self" shorthand in filters, so you need the real value. It doesn’t change, so cache it for the duration of a script.
Fill out your check-in
The find-then-PATCH dance from the section above, end to end. Resolve your UUID with GET /me (skip if you already have it), then find today’s pre-generated record:
GET /check-ins?since=2026-05-04&until=2026-05-04&people_ids[]={my_id}
PATCH that record with your answers:
PATCH /check-ins/{id}
Content-Type: application/json
{
"previous": "- Shipped X\n- Reviewed Y\n",
"intentions": "- Roll X to prod\n",
"blockers": "",
"mood": "focused",
"previous_completed": true
}
team_ids is optional in the body — omit it and the check-in defaults to all the person’s teams.
Post a goal update
A normal create, in contrast with the check-in flow — one call:
POST /goals/{goal_id}/goal-updates
Content-Type: application/json
{
"title": "Shipped the new onboarding flow",
"body": "Rolled out to 100% of new teams this week.",
"progress": 75,
"confidence": 90
}
Two quirks worth knowing:
- Nested on create and list, flat on access. Create and list updates via
POST/GET /goals/{goal_id}/goal-updates; read, update, or delete an individual update at the flatGET/PATCH/DELETE /goal-updates/{id}. confidencesnaps to 30, 60, or 90 on save (off track / at risk / on track). Bothprogressandconfidencedefault to the previous update’s values, so omit them when you only want to update the prose.
Pull recent check-ins
Filter by date range and paginate:
GET /check-ins?since=2026-05-04&until=2026-05-08&page=1&per_page=30
Both since and until are inclusive. This is how you’d assemble a weekly recap.
Find who’s blocked this week
Add the blocked filter to the same endpoint:
GET /check-ins?since=2026-05-04&until=2026-05-08&blocked=true
Pull activity for a team
GET /activities accepts team_ids[] and kinds[] filters:
GET /activities?team_ids[]={team_id}&kinds[]=github_pr&kinds[]=jira
Look up a team’s UUID via GET /teams or from the teams[] array on /me.
Downloadable resources
Building on the API with an AI coding agent? These package the guidance on this site into a single reference you can hand to your tools:
- steady-api.md — a Markdown reference covering authentication, rate limits, conventions, and the patterns above. Drop it into any agent’s context.
- steady-api.skill — the same guidance packaged as a Claude skill for Claude Code and other compatible agents.