Authentication
How LearnCoin API keys work — issuing, scoping, rotating, revoking.
Every request to the LearnCoin API is authenticated with a Bearer token in the Authorization header. There is no OAuth flow, no login cookie, no client-side JWT — just a long-lived API key you keep server-side.
Key shape
lrn_test_01HXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # testnet (Base Sepolia)
lrn_live_01HXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # production (Base mainnet)lrn_test_prefix → credentials are anchored on Base Sepolia. Free forever on the Developer tier.lrn_live_prefix → credentials are anchored on Base mainnet. Starter tier ($149/mo) and up.- 32 bytes of entropy, base58-encoded after the prefix. Treat like any other bearer secret: never commit to source control, never send in query strings, never log.
Sending the key
Authorization: Bearer lrn_test_01HXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: application/json// TypeScript
const res = await fetch("https://api.learncoin.me/v1/batches", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LEARNCOIN_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});# Python
import os, requests
res = requests.post(
"https://api.learncoin.me/v1/batches",
headers={
"Authorization": f"Bearer {os.environ['LEARNCOIN_API_KEY']}",
"Content-Type": "application/json",
},
json=payload,
)Scoping
Each API key is scoped to exactly one tenant (your organization's account) and one environment (test or live). A lrn_test_ key cannot issue on mainnet, and vice-versa. A key for tenant A cannot read batches belonging to tenant B — cross-tenant access is not a configurable option.
Retrieve the tenant a key belongs to via:
GET /v1/tenants/me
Authorization: Bearer lrn_test_…{
"id": "tnt_01HXYZ…",
"name": "Example University",
"did": "did:web:learncoin.me#tenant-01HXYZ",
"plan": "developer",
"environment": "test"
}Rotation
Keys are long-lived by default but rotate at will.
- Generate a new key via the admin console (or email [email protected] while self-serve is rolling out).
- Deploy the new key to your backend. Both old and new keys work during the overlap.
- Revoke the old key once you've confirmed the new one.
The overlap window is unbounded — LearnCoin never force-expires a key. Rotate on your own schedule, or immediately after any suspected leak.
Revocation
Revocation is immediate. Any in-flight request using a revoked key returns 401 Unauthorized with error code api_key_revoked. Already-issued credentials are unaffected — they stay on-chain, stay verifiable, and remain owned by the recipients.
IP allowlisting
Available on the Institution tier and above. Restrict which source IPs may present a given API key. Misconfigured allowlists fail closed (401 with ip_not_allowed).
Audit log
Every authenticated API call is logged with:
request_id(ULID, also returned in every response body andX-Request-Idheader)- Tenant ID
- Key ID (not the raw key)
- Endpoint + HTTP method
- Status code
- Timestamp (ISO 8601 UTC)
Logs are retained for 90 days on Developer / Starter, 365 days on Institution / Industry. Export via [email protected].
Common errors
| Status | error.code | Meaning |
|---|---|---|
| 401 | api_key_missing | No Authorization header sent. |
| 401 | api_key_invalid | Key format is wrong or key doesn't exist. |
| 401 | api_key_revoked | Key existed but was revoked. |
| 401 | ip_not_allowed | Key has IP allowlisting and the request source isn't allowlisted. |
| 403 | environment_mismatch | Using a lrn_test_ key on a mainnet-only endpoint (rare). |
Full error catalog: /docs/api/errors.
Getting a key
Developer-tier keys are provisioned manually while self-serve onboarding rolls out. Email [email protected] with one line on what you're integrating — typical turnaround is hours, not days.