Live on Base with Ewance

See the certificates
API Reference

Error codes

Every error.code the LearnCoin API can return, what it means, and how to recover.

Every non-2xx response shares this body shape:

{
  "error": {
    "code": "credential_not_found",
    "message": "Human-readable description of what went wrong.",
    "request_id": "req_01HXYZABCDEF"
  }
}

The request_id is also returned in the X-Request-Id response header. Include it when contacting support — it's the fastest way to pin down a specific call in our audit log.

Authentication — 401 Unauthorized

error.codeCauseFix
api_key_missingNo Authorization header on the request.Send Authorization: Bearer lrn_test_….
api_key_invalidMalformed key, wrong prefix, or unknown key.Re-check the key. New keys: [email protected].
api_key_revokedKey existed but was explicitly revoked.Rotate to a new key.
ip_not_allowedKey has IP allowlisting; request source isn't allowlisted.Add the source IP to the key's allowlist in the admin console.

Authorization — 403 Forbidden

error.codeCauseFix
environment_mismatchlrn_test_ key used on a mainnet-only endpoint.Use a lrn_live_ key or switch endpoint.
tier_requiredFeature needs a higher plan (e.g. custom DID on Institution).Upgrade plan or remove the feature flag.
credential_not_ownedTenant A trying to mutate Tenant B's credential.Use a key scoped to the owning tenant.

Validation — 400 Bad Request

error.codeCauseFix
invalid_jsonRequest body isn't valid JSON.Validate your JSON payload.
missing_required_fieldA required field is absent.error.message names the missing field.
invalid_field_formatA field is present but malformed (e.g. issuanceDate isn't ISO 8601).error.message names the field + expected format.
recipient_id_invalidrecipient.id isn't a urn:uuid:… form.Use urn:uuid:<v4 UUID>.
achievement_too_largeAchievement payload exceeds 64 KB.Trim or split into multiple credentials.
batch_too_largeMore than 500 credentials in one batch.Split across multiple POST /v1/batches calls.
alignment_framework_unknownalignment[].targetFramework isn't in the supported list.Use ESCO, O*NET, ISCED-F, or CUSTOM.

Not found — 404 Not Found

error.codeCause
batch_not_foundNo batch with that ID exists for this tenant.
credential_not_foundNo credential with that ID.
webhook_not_foundNo webhook endpoint with that ID.
tenant_not_foundTenant lookup by ID failed.

Conflict — 409 Conflict

error.codeCauseFix
idempotency_key_reusedSame Idempotency-Key used for a different request body.Change the key, or resend the original body.
credential_already_revokedTrying to revoke a credential that's already revoked.Skip the call; the state is already what you want.
credential_already_erasedTrying to erase a credential that's already erased.Skip the call.

Rate limit — 429 Too Many Requests

error.codeCause
rate_limitedToo many requests per minute. See Retry-After header for seconds until retry.

Default limit: 120 requests / minute / tenant across all endpoints. Institution and Industry tiers have higher limits. POSTs that spawn background work (e.g. /v1/batches) count as one request regardless of batch size.

Issuance — 422 Unprocessable Entity

Surface only from POST /v1/batches when the payload is syntactically valid but semantically can't be issued.

error.codeCause
monthly_quota_exceededTenant's plan credential quota for the month is used up.
signing_key_unavailableGCP KMS signing key is temporarily unreachable (rare, auto-retries).
anchoring_chain_unavailableBase RPC is down (rare, batch queues for retry).

Server — 500 Internal Server Error

error.codeCause
internal_errorSomething broke on our side. Every instance is paged. Retry with an idempotency key and contact support with the request_id.

Retrying

Rule of thumb:

  • 2xx — success, stop.
  • 4xx (except 429) — don't retry, the body won't change. Fix the payload.
  • 429 — back off by the Retry-After header. Exponential backoff after that.
  • 5xx — retry with exponential backoff (start 1 s, cap 30 s, jitter). Use Idempotency-Key so the retry is safe.

Getting help

Include the request_id from the response body or X-Request-Id header when you email [email protected]. We can look up the exact call in our audit log within seconds.

On this page