0.x — pre-release, no compatibility promise yet.What this means
Errors
What this is: the one shape every error has, and the list of types.
When you need it: writing the except / catch around any call.
curl -i "$TASKSMATE_API_URL/v1/tasks/T0000000" \ -H "Authorization: Bearer $TASKSMATE_TOKEN"from tasksmate import InsufficientScopeError, NotFoundError, TasksMateError
try: tm.tasks.read("T0000000")except NotFoundError: ...except InsufficientScopeError as exc: print("this token needs", exc.required_scope)except TasksMateError as exc: print(exc.status, exc.type, "— quote request_id", exc.request_id)tm tasks get T0000000# exit code 1; the problem is printed with its request_idThe shape
Section titled “The shape”Every error is application/problem+json (RFC 9457):
| Field | Type | Meaning |
|---|---|---|
type | string | about:blank or a urn:tasksmate:problem:* identifier |
title | string | e.g. "Forbidden" |
status | integer | e.g. 403 |
detail | any | Human-readable explanation (a string; for a 422, the list of validation errors) |
instance | string | e.g. "/v1/tasks/T123" |
request_id | string | e.g. "9b2f1c1e-8c1a-4a53-9f9e-0f5f1f2d7c11" |
errors (optional) | array | Structured failures: validation errors, or {loc, msg, allowed} for a bad parameter |
Branch on status and type. Show detail to people. When you ask for help, quote request_id — it is also the
X-Request-ID response header.
Problem types
Section titled “Problem types”| Status | type | What happened — and what to do |
|---|---|---|
| any | about:blank | A plain HTTP error; the status and detail say everything. |
| 422 | …:validation | The request body or query did not validate. errors lists each failure (loc, msg, type). |
| 400 | …:invalid-parameter | A query parameter is outside what the operation accepts; errors[].allowed lists the valid values. |
| 412 | …:precondition-failed | If-Match did not match the resource's current ETag — re-read it and retry. |
| 422 | …:idempotency-key-reused | This Idempotency-Key was first used for a different request (method, path or body). |
| 409 | …:idempotency-key-in-flight | The first request with this Idempotency-Key has not finished; retry shortly. |
| 400 | …:idempotency-key-invalid | Idempotency-Key must be 1–255 printable ASCII characters. |
| 429 | …:rate-limit | Too many requests with this access token; wait Retry-After seconds (X-RateLimit-* say where you stand). |
| 500 | …:internal | An unexpected server error. Quote request_id to support. |
| 401 | …:token-invalid | The access token is unknown or malformed (or its principal no longer exists). |
| 401 | …:token-expired | The access token is past its expires_at; mint a new one. |
| 401 | …:token-revoked | The access token was revoked (by its owner, an admin, a rotation, or its service account's deactivation). |
| 403 | …:insufficient-scope | The access token does not carry the scope this operation needs (errors[0].required; null = not available to tokens). |
| 403 | …:test-token-read-only | A tm_test_ token can authenticate and read, never write. |
| 403 · 422 | …:token-policy | The organization's token policy refuses this token (personal tokens off, expiry required, or past the maximum lifetime). |
| 422 | …:url-refused | The webhook URL is refused: not https, carries credentials, or resolves to a private, loopback, link-local, metadata, multicast or reserved address (errors[0].reason). |
…: is urn:tasksmate:problem:. The identifiers never change; match on them, not on title or detail.
The Python SDK raises one exception class per type (Python SDK → Errors).