Skip to content

Developer API ​

The Developer API is Kinderpedia's HTTP interface for external automation tools — Make.com, n8n, Zapier, your bespoke scripts. It lets you read leads, create notes, complete activities, register stage transitions, and subscribe to outbound webhooks. All authenticated via API keys you control.

Different from the in-app JWT-cookie API used by the SPA itself (which is browser-only). The Developer API is designed for server-to-server.

What you can do ​

  • Read your roster: leads, notes, activities, pipelines, stages, applicant statuses, forms
  • Write: create + update leads, create notes, complete activities, transition stages, archive/unarchive
  • Subscribe to events: outbound webhooks fire when things happen (lead created, stage moved, note added, etc.)
  • Idempotently retry: every POST/PUT accepts an Idempotency-Key header; duplicates replay the same response for 24h

What you cannot do ​

  • Use the Developer API as a frontend — there's no XHR-compatible session, no CSRF flow
  • Access another school's data — keys are tightly scoped to one school
  • Bypass rate limits — 60 requests/minute per key, hard 429s outside that window
  • Trigger writes outside the v1 surface — only the documented endpoints are exposed (we don't proxy the SPA API)

API key model ​

Keys look like GitHub PATs: kpa_live_<random>. Stored as SHA-256 hash on the server, never plaintext. The raw key is shown once at creation — copy it then or rotate.

See API keys for the full lifecycle (creation, rotation, revocation, expiry).

Auth header ​

Every request:

Authorization: Bearer kpa_live_…
Content-Type: application/json

The bearer token resolves to a per-school identity. There's no separate X-KINDERGARTEN-ID header (unlike the SPA API) — the key already binds you.

Endpoint structure ​

All endpoints live under /api/v1/:

GET    /api/v1/whoami
GET    /api/v1/leads
GET    /api/v1/leads/{id}
POST   /api/v1/leads
PUT    /api/v1/leads/{id}
POST   /api/v1/leads/{id}/archive
POST   /api/v1/leads/{id}/unarchive
POST   /api/v1/leads/{id}/transition
GET    /api/v1/leads/{id}/notes
POST   /api/v1/leads/{id}/notes
GET    /api/v1/leads/{id}/activities
POST   /api/v1/leads/{id}/activities
POST   /api/v1/leads/{id}/activities/{aid}/complete
GET    /api/v1/pipelines
GET    /api/v1/stages
GET    /api/v1/applicant-statuses
GET    /api/v1/forms

Plus the no-auth meta endpoint:

GET    /api/v1/openapi.json

For complete schemas + request/response shapes, see OpenAPI reference.

Versioning ​

The /v1 prefix is the current and only version. Breaking changes will move to /v2 (when applicable); v1 will stay supported for at least 12 months after v2 ships.

Backward-compatible additions (new endpoints, new optional fields) happen on v1 without notice — your existing integrations keep working.

Cursor pagination ​

List endpoints use opaque cursor pagination:

GET /api/v1/leads?after=eyJpZCI6MTIzfQ&limit=50

Response includes a Link header for the next page:

Link: <https://.../api/v1/leads?after=eyJpZCI6MTczfQ&limit=50>; rel="next"

When the response has no Link header (or no next rel), you've reached the end. Don't try to compute total counts or offset — pagination is forward-only.

Field names ​

The public API uses simplified field names, not the raw DB column names:

PublicDB column
emailstudent_email
phonestudent_phone
is_applicantderived from roster_type === 'applicant'
parent_emailfrom linked parents.email

Most of the mapping is in LeadV1Controller::PUBLIC_TO_COLUMN. The OpenAPI document is the canonical reference.

Errors ​

Errors return JSON:

{
  "error": "validation_failed",
  "message": "Field 'parent_email' must be a valid email address.",
  "details": {
    "field": "parent_email"
  }
}

HTTP status codes:

CodeMeaning
200OK
201Created
400Validation error / bad input
401Invalid / missing API key
403Key valid but missing required scope
404Resource not found (or not in your school)
409Conflict (idempotency replay with different body)
422Business rule violation (e.g. stage transition not allowed)
429Rate limit exceeded
5xxServer error — safe to retry

Scopes (planned) ​

Keys currently have a single scope: full access to v1. Future versions will introduce granular scopes (leads:read, leads:write, notes:write) — for now, treat every key as having full v1 access.

Pages in this section ​

Quick example ​

bash
# Whoami — confirm key works
curl -H "Authorization: Bearer kpa_live_xxx" \
  https://your-kinderpedia.com/api/v1/whoami

# List leads
curl -H "Authorization: Bearer kpa_live_xxx" \
  "https://your-kinderpedia.com/api/v1/leads?limit=10"

# Create a lead
curl -X POST \
  -H "Authorization: Bearer kpa_live_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-unique-key-001" \
  -d '{"student_name":"Anna Smith","parent_email":"[email protected]","form_id":1}' \
  https://your-kinderpedia.com/api/v1/leads

Kinderpedia Admissions Help Center