API Reference
Corral exposes a REST API mounted in your app. All endpoints are under
/api/auth and /api/billing by default (configurable).
/api/auth/*
Billing endpoints: /api/billing/*
Endpoint Index (v0.4.1)
Auth: /session, /sign-up/email, /sign-in/email, /sign-in/social, /sign-out, /verify-email,
/forgot-password, /reset-password, /magic-link, /otp/send, /otp/verify,
/device/authorize, /device/token, /device/verify, /keys, /keys/:id
Billing: /checkout, /portal, /cancel, /reactivate, /webhook,
/usage/track, /usage/:meter, /plans, /subscription
Admin: /admin/users, /admin/users/:id/promote, /admin/users/:id/planAuthentication
Most endpoints require authentication. Pass credentials using:
- Session cookie โ Set by Corral after sign-in. Used automatically by browsers.
- Bearer token โ
Authorization: Bearer <token>. Use for API clients, CLI tools, and non-browser requests. - API Key โ
X-API-Key: <key>. For server-to-server calls. Created via the API keys endpoint.
Auth Endpoints
Returns the current user's session, plan, and feature list. No authentication required โ returns null user for anonymous requests.
Response
{
"user": {
"id": "usr_01HN2X...",
"email": "alice@horizon.mil",
"name": "Alice Chen",
"image": "https://lh3.googleusercontent.com/...",
"role": "user",
"createdAt": "2024-01-15T09:23:00Z"
},
"plan": {
"id": "pro",
"status": "active",
"currentPeriodEnd": "2024-02-15T09:23:00Z"
},
"features": ["basic_search", "export_csv", "ai_analysis", "real_time_feed"],
"limits": {
"api_calls": 10000,
"export_rows": 100000
}
}Anonymous response
{ "user": null, "plan": { "id": "anonymous" }, "features": [], "limits": {} }Request
{
"email": "alice@horizon.mil",
"password": "hunter2",
"name": "Alice Chen"
}Response โ 200 OK
{ "user": { "id": "usr_01HN2X...", "email": "alice@horizon.mil" }, "token": "..." }Magic link request
{ "email": "alice@horizon.mil", "callbackURL": "/dashboard" }Response โ 200 OK (magic link sent)
{ "status": "magic_link_sent", "email": "alice@horizon.mil" }Request
{ "provider": "google", "callbackURL": "/dashboard" }Response โ 200 OK
{ "url": "https://accounts.google.com/o/oauth2/auth?..." }Redirect the user to url to complete OAuth.
Clears the session cookie and invalidates the session in the database.
Response โ 200 OK
{ "status": "signed_out" }Request
{ "token": "ml_01HN2X..." }Response โ 200 OK (sets session cookie)
{ "status": "verified", "user": { ... }, "token": "..." }Billing Endpoints
Requires authentication.
Request
{
"plan": "pro",
"successUrl": "https://horizon.mil/dashboard?upgraded=1",
"cancelUrl": "https://horizon.mil/pricing"
}Response โ 200 OK
{ "url": "https://checkout.stripe.com/c/pay/cs_test_..." }Requires authentication. Query params: ?return_url=/dashboard
Redirects (302) to the Stripe Customer Portal URL for the authenticated user.
Requires authentication. Cancels at end of current billing period (not immediately).
Response
{
"status": "canceled",
"active_until": "2024-02-15T09:23:00Z"
}Only works if the subscription hasn't ended yet (still in grace period).
Response
{ "status": "active", "plan": "pro" }
Receives Stripe events. Verified using STRIPE_WEBHOOK_SECRET.
Do not call this endpoint directly โ it's for Stripe only.
Register this URL in Stripe Dashboard โ Webhooks โ Add Endpoint, or use:
corral stripe push # registers webhook automaticallyDevice Auth Endpoints
Implements RFC 8628 Device Authorization Grant.
Request
{ "client_id": "horizon-cli", "scope": "openid profile" }Response โ 200 OK
{
"device_code": "dc_01HN2X...",
"user_code": "XKCD-9821",
"verification_uri": "https://horizon.mil/auth/activate",
"verification_uri_complete": "https://horizon.mil/auth/activate?code=XKCD-9821",
"expires_in": 300,
"interval": 5
}Poll at the interval returned by /device/authorize.
Request
{
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
"device_code": "dc_01HN2X...",
"client_id": "horizon-cli"
}Response โ Pending (user hasn't approved yet)
{ "error": "authorization_pending" } // keep pollingResponse โ Approved
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rt_01HN2X...",
"scope": "openid profile"
}Called from the browser approval page. Requires user to be authenticated.
Request
{ "user_code": "XKCD-9821" }Response โ 200 OK
{ "status": "approved", "client_id": "horizon-cli" }API Key Endpoints
Requires authentication. The key is shown once โ store it securely.
Request
{
"name": "horizon-cli production",
"scopes": ["api:read", "api:write"],
"expiresIn": "90d"
}Response โ 201 Created
{
"id": "key_01HN2X...",
"key": "ck_live_01HN2X...", // shown once
"name": "horizon-cli production",
"scopes": ["api:read", "api:write"],
"expiresAt": "2024-04-15T09:23:00Z"
}Returns all API keys for the authenticated user. Key values are not returned (only metadata).
Response
{
"keys": [
{ "id": "key_01HN2X...", "name": "horizon-cli production", "lastUsed": "2024-01-15" }
]
}Response โ 200 OK
{ "status": "revoked" }Usage Meter Endpoints
Increment a usage meter for the authenticated user.
Request
{ "meter": "api_calls", "amount": 1 }Response โ 200 OK
{
"meter": "api_calls",
"used": 1247,
"limit": 10000,
"remaining": 8753,
"resetsAt": "2024-02-01T00:00:00Z"
}Response โ 429 (limit exceeded)
{
"error": "meter_exceeded",
"meter": "api_calls",
"limit": 500,
"used": 500,
"resetsAt": "2024-02-01T00:00:00Z",
"upgrade_url": "/pricing"
}Response
{
"meter": "api_calls",
"used": 1247,
"limit": 10000,
"remaining": 8753,
"percent": 12.47,
"resetsAt": "2024-02-01T00:00:00Z"
}Admin Endpoints
All admin endpoints require role: admin.
Query params
?page=1&limit=50&plan=pro&search=alice
Response
{
"users": [ { "id": "...", "email": "...", "plan": "pro", "createdAt": "..." } ],
"total": 1284,
"page": 1,
"pages": 26
}Request
{ "role": "admin" }
// or:
{ "plan": "enterprise", "skip_stripe": true }Response
{ "status": "ok", "user": { "id": "...", "role": "admin", "plan": "pro" } }