Skip to content

Backend API Overview

The Inklet backend exposes a RESTful JSON API for authentication, device management, and billing. The backend is built with Go and the Chi router.

Base URL

The Inklet backend uses two production domains, split by path prefix:

Path Prefix Production Domain
/auth/* https://auth.iminklet.com
/api/*, /health https://dev.iminklet.com

For local development, both prefixes share http://localhost:4000.

Response Format

All responses return JSON with appropriate HTTP status codes. Successful responses use 200 or 201; errors return a JSON body with an error field:

{
  "error": "description of the error"
}

Authentication

Protected endpoints require a valid JWT access token in the Authorization header:

Authorization: Bearer {accessToken}

Access tokens are long-lived with a sliding renewal mechanism. Use the refresh endpoint to obtain new tokens without re-authenticating.

Token Lifecycle

Access tokens expire after 72 hours by default (configurable via the ACCESS_TOKEN_EXPIRY environment variable). Refresh tokens are long-lived but are rotated on each use --- the old refresh token is invalidated when a new pair is issued.

Sliding Renewal (X-Renewed-Token)

When an access token has less than 24 hours remaining, the backend automatically issues a fresh token on every authenticated request via the response header:

X-Renewed-Token: eyJhbGciOiJIUzI1NiIs...

Clients should inspect this header and, if present, replace the stored access token with the new value. This avoids needing to call the refresh endpoint proactively. The header is exposed in the CORS ExposedHeaders configuration so browsers can read it directly.

API Groups

The API is organized into four groups:

Auth (/auth/*) — https://auth.iminklet.com

User registration, login, OAuth (Google and Apple), session management, profile updates, and subscription billing.

See: Authentication | Billing

Devices (/api/devices/*) — https://dev.iminklet.com

Device listing, binding (NFC and claim code), unbinding, command delivery, and state retrieval.

See: Devices

Content (/api/*) — https://dev.iminklet.com

Raw content upload (text and attachment bundles), file download, and manual analyze trigger.

See: Content Upload | Worker Pipeline

  • POST /api/raw-items/upload — request presigned upload URLs
  • POST /api/raw-items/{id}/confirm — confirm files are uploaded
  • GET /api/raw-items — list the authenticated user's items
  • GET /api/raw-items/{id} — get a single item
  • GET /api/raw-items/stats — last-7-day processing stats
  • GET /api/files/{fileId}/download — get a file download redirect
  • POST /api/analyze/trigger — manually trigger an analyze run (auth required)

Health (/health) — https://dev.iminklet.com

A simple health check endpoint used by load balancers and monitoring.

curl https://dev.iminklet.com/health
{
  "status": "ok"
}

Common HTTP Status Codes

Code Meaning
200 Success
201 Resource created
400 Bad request --- invalid or missing fields
401 Unauthorized --- missing or expired token
403 Forbidden --- you do not own this resource
404 Resource not found
409 Conflict --- duplicate email, username, or device already bound
410 Gone --- resource has been deleted or expired
500 Internal server error

Rate Limiting

API requests may be rate-limited in production. If you exceed the limit, you will receive a 429 Too Many Requests response. Back off and retry after the Retry-After header value.

CORS

The production backend allows cross-origin requests from https://portal.iminklet.com. Local development allows http://localhost:5173.