For the brave.
No exercises and no congratulations at the end — just the endpoints, in order, with examples that actually run.
The API is hosted at api.sheepit.ai — every published SDK defaults to it.
API key types
Sheepit uses bearer tokens. Every key is prefixed by what it can do, so you can tell at a glance whether you've checked the right one into the right place.
lp_pub_…PublishableClient-side SDK key. Safe to ship in browser and mobile bundles. Can read /v1/config and post events. Cannot touch admin routes.
lp_sec_…SecretServer-side SDK key with full project access. Used by server SDKs. Never embed client-side.
lp_dev_…Dev / CLIRead-only access to schemas and definitions. Powers @sheepit-ai/cli codegen. Safe for dev shell + CI secrets, not client bundles.
Send the key as Authorization: Bearer <key>. Every request that needs auth needs this header.
Send one event
Paste this into a terminal. Replace the key. If the response is { "data": { "accepted": 1 } }, you're done — the event is in the dashboard.
curl -X POST https://api.sheepit.ai/v1/ingest \
-H "Authorization: Bearer lp_pub_xxx_…" \
-H "Content-Type: application/json" \
-d '{
"batch": [
{
"type": "track",
"event": "signup",
"properties": {
"source": "docs"
}
}
],
"context": {
"user": {
"anonymous_id": "anon-abc"
}
},
"sent_at": "2026-05-26T18:00:00Z"
}'That's the whole loop. Everything else in this page is a variation on the same shape.
Endpoints
The endpoints the SDKs call today. New ones land here as we ship them.
/v1/devices/registerpublishable keyRegister an anonymous device on app boot. Returns a device ID you store locally.
/v1/devices/:deviceId/identifypublishable keyAttach a user ID to a previously-registered device.
/v1/configpublishable keySnapshot of all flags + experiment assignments for the current device / user. Cache it; refresh on app foreground.
/v1/ingestpublishable keySend one or many events in a single batch. Fire-and-forget; client SDKs queue and retry.
/v1/crashes/reportpublishable keySubmit a crash report. Used by the mobile SDKs.
/v1/performance/ingestpublishable keyBatched performance metrics (startup time, frame drops, ANR, network spans).
What can go wrong
All errors come back as { "error": { "code", "message" } }. The code is stable; the message is human-readable.
| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_ERROR | Body didn't parse, or required fields were missing. |
| 401 | UNAUTHORIZED | Missing or malformed Authorization header. |
| 403 | FORBIDDEN | Key is real but doesn't have permission for this route (e.g. pub key on admin route). |
| 404 | NOT_FOUND | Resource doesn't exist or isn't visible to your project. |
| 409 | CONFLICT | A resource you tried to create already exists (e.g. a project slug that's taken). Duplicate events aren't a conflict — a duplicate event_id is simply deduped, not rejected. |
| 429 | RATE_LIMIT_EXCEEDED | You're sending too fast for your project's plan. Back off and retry with jitter. |
| 429 | INGEST_RATE_LIMITED | A separate per-minute cap on events sent to /v1/ingest (the rate limit above counts requests) — protects against one oversized batch draining the whole day's budget. |
| 5xx | INTERNAL_SERVER_ERROR | Our fault. SDKs already retry; if it persists, email us. |
Missing an endpoint? More are landing here as we ship them.
Ask us about one →