Call the API
Authentication, errors, idempotency, ETags, operations, pagination and events.
Everything the console and hart do goes through the REST API, so you can do it too. This guide walks through the
conventions with curl; every operation is in the REST API reference.
export HART_API=https://console.example.com/api/v1
export HART_TOKEN=hart_…Authenticate
Create an API key under Account settings → API keys, or use the one hart login made. Send it as a bearer
token:
curl -s -H "Authorization: Bearer $HART_TOKEN" "$HART_API/me"Harthelm-Authorization: Bearer … works the same. A key acts as you, with your roles; a request it may not make answers
403. Requests with a key need no CSRF header. A few operations, such as GET /version, need no key at all.
Every response carries Harthelm-Version with the server's version.
Read lists
Lists are paged by cursor: limit (1 to 200, default 50) and cursor in, items and next_cursor out.
curl -s -H "Authorization: Bearer $HART_TOKEN" "$HART_API/workspaces?team=7&limit=20"When next_cursor is present, pass it as cursor for the next page; when it is missing, you have everything.
Create things once
Creates accept an Idempotency-Key header. Repeating a request with the same key within 24 hours returns the first
result instead of creating a second thing, so a retry after a timeout is safe:
curl -s -X POST "$HART_API/workspaces" \
-H "Authorization: Bearer $HART_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: create-shop-$(date +%Y%m%d)" \
-d '{"team_id": 7, "name": "shop", "plan": "ide-s", "base_image": "ubuntu"}'GET /plans and GET /base-images list the plan and base image ids your installation offers; ubuntu stands for
one of them.
Follow long-running actions
Actions that outlive the request, such as creating a workspace or a Sync, answer 202 with an operation. Its URL
is in the Location header, and the body has it too:
{
"workspace": { "id": 42, "state": "creating" },
"operation": { "id": "b6a7c1d2-…", "kind": "workspace.create", "state": "running", "detail": "Configuring storage" }
}Poll it until state is succeeded or failed:
curl -s -H "Authorization: Bearer $HART_TOKEN" "$HART_API/operations/b6a7c1d2-8e4f-4a3b-9c10-5d2e7f8a9b01"A failed operation carries an error in the same problem format as below. Operations stay readable for 7 days.
Change things safely
Resources you can change return an ETag. A change sends it back as If-Match, so it never overwrites a change someone
else made in between:
etag=$(curl -s -o /dev/null -D - -H "Authorization: Bearer $HART_TOKEN" "$HART_API/workspaces/42" \
| awk 'tolower($1)=="etag:" {print $2}' | tr -d '\r')
curl -s -X PATCH "$HART_API/workspaces/42" \
-H "Authorization: Bearer $HART_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: $etag" \
-d '{"idle_timeout_minutes": 30}'A stale ETag answers 412; read the resource again and repeat the change. A missing If-Match answers 428.
Read errors
Errors are RFC 9457 problem documents, application/problem+json:
{
"type": "urn:harthelm:problem:plan-changed",
"title": "Conflict.",
"status": 409,
"detail": "The file changed since the plan was made. Plan again."
}Branch on type: it is about:blank or a URN urn:harthelm:problem:<name>, and each operation lists the ones it
returns. Validation problems add errors, one per field, with a JSON pointer, a message and, for harthelm.yml,
the line. The problem types page lists them all.
Listen to events
GET /events is a stream of server-sent events about everything you may see; ?team=7 narrows it to one team:
curl -sN -H "Authorization: Bearer $HART_TOKEN" "$HART_API/events?team=7"Each event has an id, an event type such as workspace.updated or operation.updated, and JSON data. A comment
line : ping comes every 25 seconds. There is no replay: the first event is always ready, and after every ready,
also after a reconnect, read again what you show.
The API on your installation
Every installation serves its own description at /api/v1/openapi.yaml and a browsable reference at /api/docs. Use
the description to generate a client for your language.