Skip to content

Using curl

The Sybilion API is plain HTTP/JSON. If you don't want a generated client — for shell scripts, prototypes, CI, or onboarding — these patterns get you the same coverage as the SDKs without any dependencies.

Setup

Export your API key once per shell:

bash
export SYBILION_API_TOKEN="sk_ops_..."

The base URL is https://api.sybilion.dev. To hit a non-production host, substitute the URL.

Need jq?

Most examples pipe to jq for readability. It's optional — the JSON works just as well in your code.

Authentication header

Every authenticated request takes a Bearer token:

bash
curl -sS -H "Authorization: Bearer $SYBILION_API_TOKEN" \
  https://api.sybilion.dev/api/v1/me | jq

A missing or invalid token returns 401 Unauthorized. There is no separate "verify token" endpoint — GET /api/v1/me is the canonical health check (it also tells you balance, tier, and trial state in one call).

See Authentication for the supported token types and how to get them.

Paginated lists

Listing endpoints (/usage, /jobs) share four query parameters:

ParamDefaultNotes
page11-based.
limit50Max 200 per page.
sortendpoint-specificE.g. created_at, id.
orderdescasc or desc.

The response wraps results in a pagination object:

bash
curl -sS -H "Authorization: Bearer $SYBILION_API_TOKEN" \
  "https://api.sybilion.dev/api/v1/usage?page=1&limit=50&sort=created_at&order=desc" \
  | jq '{total: .pagination.total, total_pages: .pagination.total_pages, first: .usage_events[0]}'

To walk every page, increment page until you've seen pagination.total_pages pages.

Polling an async job

Forecasts return 202 with a job_id. Poll GET /api/v1/forecasts/:id until settled is true, then read status and artifacts. A simple loop with jq -e exits when settled:

bash
JOB_ID="<paste job_id>"
API="https://api.sybilion.dev"

until curl -sS -H "Authorization: Bearer $SYBILION_API_TOKEN" \
  "$API/api/v1/forecasts/$JOB_ID" | jq -e '.settled == true' >/dev/null; do
  sleep 2
done

curl -sS -H "Authorization: Bearer $SYBILION_API_TOKEN" \
  "$API/api/v1/forecasts/$JOB_ID" \
  | jq '{status, eur_cents_final, artifacts: .artifacts | map(.name)}'

Forecasts run for tens of seconds to a few minutes. Pick a poll interval (2–5 seconds is fine) and add a max-duration guard for production use.

Reading the error envelope

Every error response uses the same shape. For validation:

json
{
  "error": "validation_failed",
  "details": [{ "field": "horizon", "message": "horizon must be between 1 and 12" }]
}

Validation is fail-fast — only the first offending field is reported per call. Other errors use a shorter shape:

json
{ "error": "insufficient credits" }

Common patterns:

bash
# Show only the error code on non-2xx, otherwise pretty-print the body.
RES=$(curl -sS -w "\n%{http_code}" \
  -H "Authorization: Bearer $SYBILION_API_TOKEN" \
  https://api.sybilion.dev/api/v1/forecasts \
  -d @forecast_body.json)
BODY=$(printf '%s' "$RES" | sed '$d')
CODE=$(printf '%s' "$RES" | tail -n1)

if [ "$CODE" -ge 400 ]; then
  printf 'HTTP %s — %s\n' "$CODE" "$(printf '%s' "$BODY" | jq -r '.error // .message // .')"
else
  printf '%s' "$BODY" | jq
fi

Full catalog of HTTP codes: Errors & limits.

Downloading artifacts

Forecast artifacts stream through the API at GET /api/v1/forecasts/:id/artifacts/:name — there are no direct storage URLs. Use -o to save:

bash
JOB_ID="<paste job_id>"
for ART in forecast.json external_signals.json backtest_metrics.json; do
  curl -sS -H "Authorization: Bearer $SYBILION_API_TOKEN" \
    -o "$ART" \
    "https://api.sybilion.dev/api/v1/forecasts/$JOB_ID/artifacts/$ART"
done

jq '.data.forecast_series | to_entries | .[0]' forecast.json

Artifact responses can be large (up to 100 MiB per file). Use Range headers for partial reads — the API returns 206 when honoring a range. Full artifact contract: Artifact download.

Idempotent retries

For synchronous billed calls (e.g. POST /api/v1/drivers), pass a stable X-Request-ID header on each retry to deduplicate billing on success:

bash
REQ_ID=$(uuidgen)
curl -sS -X POST https://api.sybilion.dev/api/v1/drivers \
  -H "Authorization: Bearer $SYBILION_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Request-ID: $REQ_ID" \
  -d @drivers_body.json

Useful flags

FlagWhy
-sSSilent + show errors. Hides progress bars without hiding real failures.
-w "\n%{http_code}\n"Append the HTTP status to the output for scripted handling.
-D -Dump response headers to stdout (useful for inspecting Content-Type, Content-Length).
--fail-with-bodyExit non-zero on 4xx / 5xx while still printing the body (curl 7.76+).
-o fileStream the body to disk (use for artifact downloads).
-H "Accept-Encoding: gzip"Lets the API gzip large list responses.

See also

[email protected] · Slack · Discord (links in Community page & header icons)