Sign in

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: date fields are YYYY-MM-DD; *_at fields are ISO 8601 datetimes like 2026-05-04T18:18:22Z.
  • Long-form text fields such as previous, intentions, blockers, and comment body are Markdown. Use @username to mention people — Steady links these automatically.
  • Pagination on list endpoints uses page (1-indexed) and per_page.
  • Array query parameters use the repeated name[]=value form, e.g. people_ids[]=abc&people_ids[]=def — not comma-separated.
  • Date-range filtering uses since and until on 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 flat GET/PATCH/DELETE /goal-updates/{id}.
  • confidence snaps to 30, 60, or 90 on save (off track / at risk / on track). Both progress and confidence default 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.