Integration

HTTP contract: rate limits, idempotency, errors

Retry-After, Idempotency-Key, cursors and 4xx codes — stable behaviour to implement once.

OpenAPI contractIssue an API keyFree Solo account

Full document, no authentication, ready for your client generator.

What the API does not do

Four actions stay out of a key's reach, by choice. Issuing or revoking a key. Inviting a member. Changing plan or billing. Exporting the organisation (members = personal data).

No secret comes back on read: HTTP password, webhook URL, browser AST. Instead, a fingerprint that changes when the value changes.

Rate limits

Per key and per minute: 300 reads and 60 writes, counted separately. A tool re-reading its estate must not exhaust the write budget.

Beyond → 429 with Retry-After in seconds. Honour it: blind retries keep the loop alive.

# Pseudo-client
# if status == 429:
#   sleep(int(headers["Retry-After"] or "1"))
#   retry()

Idempotency

Every write accepts Idempotency-Key. The first response is kept 24 h and replayed if the same key returns with the same body. Different body → 409. Failures are not remembered.

Pick a stable human key: deploy-2026-09-24-checkout, tf-pathly-scenario-home. Avoid a fresh UUID on every manual retry.

curl -X POST https://api.pathlyhq.com/v1/scenarios \
  -H "Authorization: Bearer $PATHLY_API_TOKEN" \
  -H "Idempotency-Key: deploy-2026-09-24-checkout" \
  -H "Content-Type: application/json" \
  -d '{"type":"http","name":"Checkout","url":"https://www.example.com/cart","intervalSec":300}'

Pagination

Collections: limit (default 100, max 500) and cursor. Response: nextCursor (null on last page). The cursor is opaque — pass it back as-is.

curl

curl "https://api.pathlyhq.com/v1/runs?limit=100" \
  -H "Authorization: Bearer $PATHLY_API_TOKEN"

bash — parcourir toutes les pages

cursor=
while :; do
  url="https://api.pathlyhq.com/v1/runs?limit=100"
  [ -n "$cursor" ] && url="$url&cursor=$cursor"
  page=$(curl -sS "$url" -H "Authorization: Bearer $PATHLY_API_TOKEN")
  echo "$page" | jq -c '.items[]?'
  cursor=$(echo "$page" | jq -r '.nextCursor // empty')
  [ -z "$cursor" ] && break
done

Errors

Every error has shape { "error": "…" } with a displayable message. An id from another organisation returns 404, never 403: "forbidden" would confirm it exists.

{
  "error": "Missing scope scenarios:write"
}
CodeMeaningWhat to do
400Invalid body, or business rule refusedFix the request, `details` names the offending fields
401Key missing, unknown, revoked or expiredRenew the key
403Insufficient scope, or feature not in the planWiden the key, or the plan
404Resource does not exist in this organisationTreat it as deleted
409Idempotency key reused with a different bodyChange the idempotency key
429Rate limit exceededWait the number of seconds given by `Retry-After`