REST API
All endpoints are under /api/v1. Requests and responses use JSON.
Authentication
There are two authentication modes depending on the operation:
otakit_sk_...) or a user access token from otakit login. The app ID is part of the URL path.# CLI / server operations Authorization: Bearer otakit_sk_... # or OTAKIT_ACCESS_TOKEN # Plugin operations X-Public-Key: otakit_pk_...
Apps
Create a new app. The slug should match your Capacitor app identifier. Returns an appId and publicKey for plugin config.
Auth: Bearer
Request body
{ "slug": "com.example.myapp" }Response
{
"id": "uuid",
"slug": "com.example.myapp",
"publicKey": "otakit_pk_...",
"createdAt": "ISO timestamp"
}Bundles
Start a bundle upload. Returns a presigned PUT URL. Upload your zip file to this URL with Content-Type: application/zip.
Auth: Bearer
Request body
{
"version": "1.0.1", // semver string
"size": 1048576, // bundle size in bytes
"minNativeBuild": 100 // optional
}Response
{
"uploadId": "uuid",
"presignedUrl": "https://...",
"storageKey": "...",
"expiresAt": "ISO timestamp"
}Finalize a bundle upload. The server verifies the SHA-256 hash matches. Creates the bundle record.
Auth: Bearer
Request body
{
"uploadId": "uuid",
"sha256": "64-char hex hash"
}Response
{
"id": "uuid",
"version": "1.0.1",
"sha256": "...",
"size": 1048576,
"minNativeBuild": null,
"createdAt": "ISO timestamp"
}List bundles sorted by creation date (newest first).
Auth: Bearer · Query: ?limit=20&offset=0
Response
{
"bundles": [{ id, version, sha256, size, createdAt }],
"total": 42
}Delete a bundle. Bundles that are part of a release history cannot be deleted.
Auth: Bearer
Response
{ "deleted": true, "id": "uuid" }Channels
Release a bundle to a channel. One bundle = one release.
Auth: Bearer
Request body
{
"bundleId": "uuid"
}Response
{
"channel": "default",
"release": {
"id": "uuid",
"bundleId": "uuid",
"bundleVersion": "1.0.1",
"position": 5,
"promotedAt": "ISO timestamp"
},
"previousRelease": { ... } | null
}Roll back a channel by N releases. Creates a new release pointing to the older bundle.
Auth: Bearer
Request body
{
"steps": 1 // optional, default 1, max 100
}Response
{
"channel": "default",
"release": { ... },
"rolledBackFrom": { ... }
}List release history for a channel, sorted by position (newest first).
Auth: Bearer · Query: ?limit=20&offset=0
Response
{
"releases": [{
id, bundleId, bundleVersion, position, promotedAt
}],
"total": 12
}Manifest (Plugin)
Check for the latest bundle on a channel. Used by the Capacitor plugin. Returns a signed download URL with 10-minute TTL. X-Platform is used for manifest signature only.
Auth: X-Public-Key
Headers
X-Public-Key: otakit_pk_... X-Platform: ios X-Current-Version: 1.0.0 // optional X-Native-Build: 100 // optional
Response
// 204 No Content — already up to date
// 200 OK — update available
{
"version": "1.0.1",
"channel": "default",
"releaseId": "release_uuid",
"url": "https://... (signed, 10min TTL)",
"sha256": "...",
"size": 1048576,
"minNativeBuild": null,
"signature": { "kid": "...", "sig": "...", "iat": ..., "exp": ... }
}
// 406 Not Acceptable — native build too old
{ "error": "native_build_too_old", "minNativeBuild": 200 }Device Events
Record a device event for analytics. Used by the plugin to report update lifecycle events.
Auth: X-Public-Key
Request body
{
"platform": "ios",
"action": "downloaded", // downloaded, success, error
"bundleVersion": "1.0.1", // optional
"channel": "default", // optional
"releaseId": "release_uuid",// optional
"errorMessage": "..." // optional, max 500 chars
}Response
{ "success": true }CLI Options
The otakit CLI accepts a global --app-id option that overrides OTAKIT_APP_ID and capacitor.config.ts. Resolution order:
--app-id <id> # highest priority OTAKIT_APP_ID # env var capacitor.config.ts # Updater.appId