Skip to Content
API ReferenceREST API

API Reference

All API endpoints are served under /v1/ota/ and require authentication via an API key (passed as a Bearer token) and a project slug (passed as the X-Project header).

curl https://api.appdispatch.com/v1/ota/updates \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "X-Project: your-project-slug"

Authentication

Headers

HeaderDescription
AuthorizationBearer YOUR_API_KEY
X-ProjectYour project slug

Getting an API key

Create API keys from the dashboard under Settings → API Keys.


Updates

List updates

GET /v1/ota/updates

Create update

POST /v1/ota/updates

Update an update

PATCH /v1/ota/updates/{id}

Delete update

DELETE /v1/ota/updates/{id}

Republish update

POST /v1/ota/updates/{id}/republish

Republishes an existing update to additional channels or with updated release notes.

{ "channels": ["staging", "canary"], "releaseMessage": "Republished with fix" }
FieldTypeRequiredDescription
channelsstring[]NoChannels to publish to
releaseMessagestringNoUpdated release message

Returns { "updates": [...], "groupId": "uuid" }.

Get update history

GET /v1/ota/updates/{id}/history

Builds

List builds

GET /v1/ota/builds

Upload build

POST /v1/ota/builds

Multipart form upload. Fields:

FieldTypeRequiredDescription
runtimeVersionstringYesRuntime version fingerprint
platformstringYesios or android
messagestringNoRelease message
expoConfigJSONNoExpo app config
gitCommitHashstringNoGit commit hash
gitBranchstringNoGit branch name
assetsfilesYesBundle and asset files

Publish build

Publishes a build to a channel, creating an update (release).

POST /v1/ota/builds/{id}/publish
{ "channel": "production", "rolloutPercentage": 100, "isCritical": false, "releaseMessage": "v2.1 release", "groupId": "optional-uuid", "linkedFlags": [ { "flagId": 1, "enabled": true } ] }
FieldTypeRequiredDescription
channelstringYesTarget channel name
rolloutPercentagenumberNoInitial rollout percentage (0–100, default 100)
isCriticalbooleanNoMark update as critical
releaseMessagestringNoRelease notes
groupIdstringNoUUID to group multi-platform publishes together
linkedFlagsarrayNoFeature flags to link to this release
linkedFlags[].flagIdnumberYesFlag ID
linkedFlags[].enabledbooleanYesWhether the flag is enabled for this release

Delete build

DELETE /v1/ota/builds/{id}

Branches

List branches

GET /v1/ota/branches

Create branch

POST /v1/ota/branches
{ "name": "staging" }

Delete branch

DELETE /v1/ota/branches/{name}

Channels

List channels

GET /v1/ota/channels

Create channel

POST /v1/ota/channels
{ "name": "staging", "branchName": "staging" }

Update channel

PATCH /v1/ota/channels/{name}
{ "branchName": "new-branch", "rolloutBranchName": "canary", "rolloutPercentage": 10, "minRuntimeVersion": "2.0.0" }

Delete channel

DELETE /v1/ota/channels/{name}

Feature Flags

List flags

GET /v1/ota/flags

Create flag

POST /v1/ota/flags
{ "name": "New Checkout", "key": "new-checkout", "flagType": "boolean", "defaultValue": false, "enabled": true, "description": "Enable the new checkout flow", "variations": [ { "name": "On", "value": "true" }, { "name": "Off", "value": "false" } ] }

Get flag

GET /v1/ota/flags/{id}

Update flag

PATCH /v1/ota/flags/{id}

Delete flag

DELETE /v1/ota/flags/{id}

Create targeting rule

POST /v1/ota/flags/{id}/rules
{ "ruleType": "percentage_rollout", "ruleConfig": { "rollout": [ {"variantValue": "true", "weight": 50}, {"variantValue": "false", "weight": 50} ] }, "variantValue": "true", "priority": 0, "channelName": "production" }

Rule types: user_list, percentage_rollout, attribute, segment, ota_update

Segment rule example:

{ "ruleType": "segment", "ruleConfig": { "segmentKey": "ios-pro-users" }, "variantValue": "true", "priority": 2, "channelName": "production" }

Update rule

PATCH /v1/ota/flags/{id}/rules/{ruleId}

Delete rule

DELETE /v1/ota/flags/{id}/rules/{ruleId}

Update variation

PATCH /v1/ota/flags/{id}/variations/{variationId}

Update environment settings

PATCH /v1/ota/flags/{id}/env/{channelName}
{ "enabled": true, "defaultValue": "variant-a" }

Get flag evaluations

GET /v1/ota/flags/{id}/evaluations

Flag definitions (client endpoint)

GET /v1/ota/flag-definitions/{projectSlug}?channel=production

Public endpoint used by the OpenFeature provider. Returns enabled flags with their rules and variations for the specified channel.


Health Metrics

Report health events (client endpoint)

POST /v1/ota/health-metrics

Public endpoint used by the health reporter in @appdispatch/react-native. No authentication required.

{ "projectSlug": "my-app", "deviceId": "device-xyz", "channel": "production", "platform": "ios", "runtimeVersion": "49.0.0", "updateUuid": "abc-123", "events": [ { "type": "js_error", "message": "TypeError: undefined is not an object", "count": 3, "flagStates": { "new-checkout": true, "theme": "dark" } }, { "type": "app_launch", "count": 1 } ] }
FieldTypeRequiredDescription
projectSlugstringYesProject slug
deviceIdstringYesStable device identifier
channelstringNoChannel name
platformstringYes"ios" or "android"
runtimeVersionstringYesRuntime version from expo-updates
updateUuidstringNoCurrent update UUID from expo-updates
eventsarrayYesArray of health events
events[].typestringYes"js_error", "crash", "custom", or "app_launch"
events[].namestringNoEvent name (for custom events)
events[].messagestringNoError message
events[].countnumberYesNumber of occurrences (deduplicated client-side)
events[].flagStatesobjectNoFlag variations active at error time

Returns 204 No Content on success.


Segments

List segments

GET /v1/ota/segments

Create segment

POST /v1/ota/segments
{ "name": "iOS Pro Users", "key": "ios-pro-users", "description": "Pro-tier users on iOS", "matchType": "all", "conditions": [ {"attribute": "platform", "operator": "eq", "valuesJson": ["ios"]}, {"attribute": "plan", "operator": "eq", "valuesJson": ["pro"]} ] }
FieldTypeRequiredDescription
namestringYesDisplay name
keystringNoUnique key (auto-generated from name if omitted)
descriptionstringNoHuman-readable description
matchTypestringYes"all" (AND) or "any" (OR)
conditionsarrayYesArray of condition objects
conditions[].attributestringYesContext attribute name
conditions[].operatorstringYesComparison operator
conditions[].valuesJsonstring[]YesValues to match (empty for exists/not_exists)

Get segment

GET /v1/ota/segments/{id}

Update segment

PATCH /v1/ota/segments/{id}

Delete segment

DELETE /v1/ota/segments/{id}

Returns 409 Conflict if the segment is referenced by any flag rules. Remove the segment rules first.


Webhooks

List webhooks

GET /v1/ota/webhooks

Create webhook

POST /v1/ota/webhooks
{ "url": "https://your-app.example.com/webhook", "events": ["build.published", "channel.updated"], "secret": "whsec_your_signing_secret" }

Update webhook

PATCH /v1/ota/webhooks/{id}

Use isActive to enable or disable a webhook:

{ "isActive": false }

Delete webhook

DELETE /v1/ota/webhooks/{id}

Get delivery history

GET /v1/ota/webhooks/{id}/deliveries

Audit Log

List audit log

GET /v1/ota/audit-log?limit=100&before=500
ParamDescription
limitMax entries to return (default 200, max 200)
actionFilter by action (e.g., build.published)
entity_typeFilter by entity type (e.g., update, flag)
entity_idFilter by entity ID
beforeCursor: return entries with ID less than this (for pagination)

Rollback

Create rollback

POST /v1/ota/rollback
{ "runtimeVersion": "1.0.0", "platform": "ios", "channel": "production", "rollbackToUpdateId": 123 }
FieldTypeRequiredDescription
runtimeVersionstringYesRuntime version to target
platformstringYes"ios" or "android"
channelstringYesChannel name
rollbackToUpdateIdnumberNoSpecific update ID to roll back to. If omitted, rolls back to the embedded update.

User Overrides

List overrides

GET /v1/ota/user-overrides

Create override

POST /v1/ota/user-overrides
{ "userId": "user-123", "branchName": "beta-testers", "note": "QA tester for v2.1" }

Delete override

DELETE /v1/ota/user-overrides/{id}

Contexts

List contexts

GET /v1/ota/contexts

Returns all contexts for the project. Supports query parameters for filtering by kind and search.

Create context

POST /v1/ota/contexts
{ "kind": "user", "targetingKey": "user-abc-123", "name": "Alice", "attributes": { "plan": "pro", "platform": "ios" } }
FieldTypeRequiredDescription
kindstringYesContext kind: user, device, organization, service, or environment
targetingKeystringYesUnique key for this context
namestringNoDisplay name
attributesobjectNoKey-value attributes

Get context

GET /v1/ota/contexts/{id}

Delete context

DELETE /v1/ota/contexts/{id}

List context kinds

GET /v1/ota/contexts/kinds

Returns the available context kinds: user, device, organization, service, environment.


Rollout Policies

List rollout policies

GET /v1/ota/rollout-policies

Create rollout policy

POST /v1/ota/rollout-policies
{ "name": "Staged production rollout", "stages": [ { "percentage": 5, "minDevices": 100, "minDurationMinutes": 60 }, { "percentage": 25, "minDevices": 500, "minDurationMinutes": 120 }, { "percentage": 100, "minDevices": 0, "minDurationMinutes": 0 } ], "thresholds": { "errorRate": 2.0, "crashRate": 0.5, "action": "auto-rollback" } }

Get rollout policy

GET /v1/ota/rollout-policies/{id}

Update rollout policy

PATCH /v1/ota/rollout-policies/{id}

Editing is locked while an execution is running for this policy.

Delete rollout policy

DELETE /v1/ota/rollout-policies/{id}

Rollout Executions

List executions

GET /v1/ota/rollout-executions

Get execution

GET /v1/ota/rollout-executions/{id}

Pause execution

POST /v1/ota/rollout-executions/{id}/pause

Resume execution

POST /v1/ota/rollout-executions/{id}/resume

Cancel execution

POST /v1/ota/rollout-executions/{id}/cancel

Advance execution

POST /v1/ota/rollout-executions/{id}/advance

Manually advances the execution to the next stage.


Flag Health

Get flag health

GET /v1/ota/flags/{id}/health

Returns health status for a flag, including error rate, crash-free percentage, affected devices, and per-variation health breakdown.


Adoption

Get adoption metrics

GET /v1/ota/insights/adoption

Returns adoption metrics including total active devices and download counts. Supports days query parameter (7, 14, 30, or 90).


Telemetry

Get timeseries data

GET /v1/ota/telemetry/timeseries

Returns time-bucketed metrics for devices, errors, and crashes over the specified period.

Get flag impacts

GET /v1/ota/telemetry/flag-impacts

Returns the flag impact matrix showing error rate and crash-free percentage per flag variation, update, and channel.

Get telemetry events

GET /v1/ota/telemetry/events

Returns raw telemetry events with filtering by type, channel, and platform.


Observe

List observe events

GET /v1/ota/observe/events

Returns errors, crashes, and custom events from devices. Supports filtering by event type (js_error, crash, custom), channel, and platform. Results are paginated (50 per page).

Last updated on