apps/api. All routes are prefixed with /api.
Authentication uses a JWT returned on login. The API sets an httpOnly cookie (certiva_access_token) and also returns an accessToken in the response body. Protected endpoints accept either the cookie or a Bearer token in the Authorization header.
Health
GET /api/health
Public liveness check. No authentication required.Authentication
POST /api/auth/login
Rate limited: 5 requests per 60 seconds (configurable).certiva_access_token as an httpOnly, sameSite: lax cookie.
GET /api/auth/me
Returns the authenticated admin’s profile.POST /api/auth/register
Create a new admin. RequiresOWNER or SUPER_ADMIN role.
Body: { username, password, role } — role is one of OWNER, SUPER_ADMIN, ADMIN, AUDITOR.
GET /api/auth/admins
List all admins. RequiresOWNER or SUPER_ADMIN.
PATCH /api/auth/admins/:id
Update an admin’s role or disabled status. RequiresOWNER or SUPER_ADMIN.
DELETE /api/auth/admins/:id
Delete an admin. RequiresOWNER or SUPER_ADMIN. Fails if the admin has any historical activity — disable instead.
Credentials
All credential write endpoints require authentication.POST /api/credentials
Issue a single credential. Body:anchorStatus is PENDING on creation and transitions to ANCHORED after the worker submits the blockchain transaction.
POST /api/credentials/bulk
Issue credentials from a CSV file. Returns abatchId — poll GET /api/batches/:id for progress.
POST /api/credentials/bulk-revoke
Body:{ ids: string[], reason: RevocationReason }
POST /api/credentials/bulk-delete
Body:{ ids: string[] }
GET /api/credentials
List credentials for the institution.GET /api/credentials/:id
Get a single credential by ID.DELETE /api/credentials/:id
Delete a credential.PATCH /api/credentials/:id/revoke
Body:{ reason: RevocationReason }
Valid reasons: DATA_CORRECTION, ISSUED_IN_ERROR, FRAUD_SUSPECTED, INSTITUTION_REQUEST, OTHER, LEGACY.
POST /api/credentials/:id/rebuild-assets
Regenerates the QR code image and metadata file for the credential. Use after changingAPI_PUBLIC_BASE_URL or WEB_PUBLIC_BASE_URL.
POST /api/credentials/:id/secure-pdf
Attach a secure PDF document proof to an existing credential.GET /api/credentials/:id/metadata
Returns the credential metadata JSON.GET /api/credentials/:id/qr
Returns the QR code image.Batches
GET /api/batches/:id
Get bulk issuance batch details, including per-row results and failure reasons.Verification
Public endpoints. No authentication required. Rate limits apply.POST /api/verify/credential/code
Rate limited: 30 requests per 60 seconds. Body:{ "verificationCode": "CERT-A1B2C3" }
POST /api/verify/credential/pdf
Rate limited: 10 requests per 60 seconds. Multipart form upload.POST /api/verify/secure-pdf
Rate limited: 10 requests per 60 seconds. Verifies a secure PDF document proof.GET /api/verify/:verificationId
Get a verification result byverificationId.
GET /api/verify/:verificationId/certificate
Download the certificate PDF for a verified credential.POST /api/verifications
General verification endpoint.POST /api/verification/upload
Rate limited: 10 requests per 60 seconds. Upload-based verification.Document Proofs
Write endpoints require authentication. Verification endpoints are public.POST /api/document-proofs
Register a document integrity proof. Multipart form upload. The source file is discarded — only the SHA-256 hash is stored. Response:GET /api/document-proofs
List document proofs for the institution.GET /api/document-proofs/:id
Get a single proof by ID.DELETE /api/document-proofs/:id
Delete a proof.POST /api/document-proofs/bulk-delete
Body:{ ids: string[] }
POST /api/document-proofs/verify/document/code
Public. Verify document proof by verification code.POST /api/document-proofs/verify/document
Public. Verify document proof by file upload (multipart).GET /api/document-proofs/:id/metadata
Returns proof metadata JSON.GET /api/document-proofs/:id/qr
Returns the proof QR code image.GET /api/document-proofs/proof/:verificationId
Public. Get proof result byverificationId.