Skip to content

Overview

Multi-tenant OTA update platform for React Native apps.

The Aether API powers over-the-air JavaScript bundle updates for React Native applications. It enables developers to push updates to deployed apps without going through the app store review process.

Authentication

Aether accepts two bearer credential families in the Authorization header:

  • Access keys have wildcard scope and full account access. Login flows such as POST /v1/auth/login create access keys with isSession: true; dashboard and CLI sessions use these credentials, and only they satisfy session-only guards. Named access keys created through POST /v1/access-keys have isSession: false and cannot call session-only endpoints.
  • API keys use the aether_sk_live_ prefix and are created through POST /v1/api-keys. These long-lived credentials have scoped permissions for CI/CD pipelines and cannot call session-only endpoints.

See securitySchemes for details.

Versioning

All management and authentication endpoints are mounted under /v1. The canonical acquisition endpoints (consumed by the React Native SDK) live at /v1/public/aether/… Legacy acquisition paths (/v0.1/public/codepush/… and the camelCase /updateCheck and /reportStatus/… aliases) remain available for backward compatibility with the react-native-code-push SDK family and early Aether installs. Legacy paths return a Deprecation header and a Link header pointing to their canonical successor and to the CodePush migration guide.

Unsupported /v1 path-parameter aliases

The /v1 management mount falls through to the pre-/v1 router for any path the REST-shaped /v1 overrides do not handle. That fall-through still answers four path-parameter shapes that are not part of this published contract and must not be called:

  • POST /v1/apps/{appName}/transfer/{email}
  • POST /v1/apps/{appName}/collaborators/{email}
  • POST /v1/apps/{appName}/deployments/{sourceDeploymentName}/promote/{destDeploymentName}
  • POST /v1/apps/{appName}/deployments/{deploymentName}/rollback[/{targetRelease}]

They are omitted from the paths below on purpose. They send no Deprecation, Link, or Sunset header (those headers apply to bare legacy management mounts and to legacy acquisition, not to these /v1 shapes). Use the REST-shaped successors instead:

  • POST /v1/apps/{appName}/transfers
  • POST /v1/apps/{appName}/collaborators (email in the body; PATCH and DELETE on /collaborators/{email} remain documented)
  • POST /v1/apps/{appName}/deployments/{sourceDeploymentName}/promotions
  • POST /v1/apps/{appName}/deployments/{deploymentName}/rollbacks

The openapi-route-contract test’s UNDOCUMENTED_V1_ROUTES list is the mechanical census of this omission; keep that list and this section in step.

Error envelope

All error responses share a canonical shape with an error string field, a stable code string field, and an optional requestId string field. Validation failures additionally include an errors array whose entries each carry their own code. See the Error and ValidationErrorResponse schemas under components. Prefer matching on code over matching on error wording. Every value an operation in this document can answer with is listed in the ApiErrorCode schema, published in full in the raw document at https://api.aetherpush.com/openapi.yaml. The set follows the server release, so treat an unrecognised value by its HTTP status alone. CLI device-flow OAuth responses are the exception: they keep the RFC machine value in error and do not add a parallel code.

JSON request bodies parsed by the JSON body parser are refused with 413 and error set to “The provided resource is too large.” when they exceed 10 KB (10,240 bytes). That parser does not run on POST /v1/billing/webhook, which uses a raw parser with a 100 KB limit, or on the multipart release upload. The release upload answers 413 in the same Error envelope when the package exceeds UPLOAD_SIZE_LIMIT_MB (default 50), when more than one file is uploaded, or when the multipart body has too many parts; error names which limit fired.

The requestId is also exposed as the X-Request-Id response header on every response and should be quoted when reporting issues.

Process-wide address limiter

Every published path on this API sits behind one process-wide address limiter mounted ahead of routing (100 requests per minute per client address). When that budget is spent the server answers HTTP 429 with Content-Type: application/json and body GlobalAddressRateLimitErrorResponse ({"error":"Too many requests","code":"too_many_requests"}), plus Retry-After and draft RateLimit-* headers (standardHeaders, no legacy X-RateLimit-*). The body does not carry retryAfterSeconds or requestId; X-Request-Id is still set as a header. No published route skips this limiter. Route-specific and tenant limiters documented on individual operations are separate budgets that can also answer 429 with different envelopes after this one admits the request.

Information

  • OpenAPI version: 3.1.0

Wildcard bearer credential backed by access_keys. Login flows create credentials with isSession: true; POST /v1/access-keys creates named credentials with isSession: false. Operations that require a login session, including billing endpoints, reject the named subtype.

While the account has a deletion scheduled (Account.deletionScheduledFor is set), every authenticated operation answers a plain 403 except GET /v1/account, DELETE /v1/account/deletion, DELETE /v1/sessions/current and GET /v1/authenticated, which only reports that the bearer is live. Signing in stays possible so the owner can cancel; the freeze lifts the moment the deletion is cancelled.

Security scheme type: http

Bearer format: AccessKey

Long-lived API key with the prefix aether_sk_live_. Created via POST /v1/api-keys. Carries a granular scope set declared at creation time. Cannot be used for billing endpoints or for session/access-key management, both of which require a login session.

Scope enforcement: every management route enforces the scope shown on its operation. deploy and apps also grant read, so a key does not need read listed explicitly to call the reads a deploy or app workflow depends on. See ApiKeyScope for the full rule.

Security scheme type: http

Bearer format: ApiKey