Getting started
API conventions
The facade uses flat JSON, explicit resource selection, bounded pages, and stable errors across its App Store Connect reads.
Read-only implementation Core app, app-info, version, localization, age-rating, and review-contact reads are implemented, along with hosted connection setup and revocation. Operator configuration remains supported. Additional reads and all resource mutations have separate milestones.
Base URL and authentication
Resource routes are relative to https://asc.example.com/v1/connections/{connectionId}. Send a facade API key as Authorization: Bearer <facade-api-key>. The service owns Apple credentials and JWTs; clients never sign Apple JWTs or send Apple relationship envelopes.
A connection ID grants no access by itself. Check the caller’s connection and resource permissions on every request, including every cursor page. A missing or invalid facade key maps to 401 unauthorized; rejected Apple credentials map to 502 upstream_authentication_failed.
Hosted connections
Create a hosted connection with POST /v1/connections and a JSON body containing exactly issuerId, keyId, and privateKey: an issuer UUID, a 10-character uppercase alphanumeric key ID, and a P-256 PKCS#8 PEM. The body limit is 8 KiB. The service validates the key locally, then makes read-only GET /v1/apps?limit=1 against Apple. A successful request returns 201 with a generated connection ID, base URL, and facade API key. Hosted IDs begin with the reserved conn_live_ prefix plus 32 hex characters; facade keys use the pq_ prefix and a random 32-byte base64url value. The facade key grants read-only access to all apps the Apple key can access. Setup is limited to 10 attempts per minute per IP and Cloudflare location.
Authenticate DELETE /v1/connections/{hostedId} with the returned facade key to remove stored Apple credentials and revoke that key; success returns 204 No Content. Hosted deployments require a SQLite Durable Object binding and migrations plus a stable 32-byte base64url CONNECTION_ENCRYPTION_KEY secret. Missing hosted storage configuration returns 503 hosted_connections_not_configured. The service encrypts stored credentials, hashes facade keys, sends API responses with no-store, and redacts secrets from logs.
Resources and selection
- Use explicit IDs for app, app-info, and version resources. Validate that each nested resource belongs to the selected parent app.
- Use an exact locale key, such as
en-US. A missing localization returns404 localization_not_found; it does not fall back to another locale. - Choose platform and version state deliberately. The
statequery maps to Apple’s currentappVersionStatefilter; read enum values are preserved. The Worker does not select the first version or silently substitute a live one for a draft. - Only the fixed, documented fields on a route are returned or writable. Read access does not imply mutation support.
JSON shape
Responses use camelCase fields, string IDs, RFC 3339 timestamps, and Apple’s enum strings. Single-resource reads return flat objects. Collections use an items array and nextCursor; they do not expose Apple’s data, attributes, or relationships envelopes or recursively expand related resources.
Preserve the difference between an omitted field, null, an empty string, false, and 0. Unsupported or read-only fields are rejected instead of being silently dropped. A collection with no matches is 200 with items: []; an upstream failure is an error response.
Pagination
Collections default to 50 items per page. A route may set a lower or higher maximum within Apple’s endpoint limits. Pass a returned opaque nextCursor back as cursor with the same connection, route, filters, and ordering. Stop when nextCursor is null.
Cursors are signed, expire after 15 minutes, and bind the caller’s grant, credential revision, resource path, filters, fields, and page size. Each page is authorized again. A cursor chain permits up to 100 pages. Internal ownership and locale resolution permit up to 20 pages; all Apple reads in a facade request share a 25-second deadline, 32-attempt budget, 4 MiB per-response limit, and 16 MiB total-body limit. Exceeding a budget returns an explicit error instead of a successful but truncated collection.
Query parameters
Routes accept only reviewed filters, sort keys, and selectors. Supported multi-value filters use comma-separated values where the endpoint documents them. Unknown parameters and unsupported combinations return 400 invalid_query. Filter and sort behavior is route-specific; it is not an arbitrary pass-through to Apple.
If a route explicitly supports a fields parameter, it selects response attributes only. It does not request Apple relationships or change resource selection. Do not send Apple’s include, filter[...], or pagination URL parameters directly.
Errors
Errors use one stable JSON envelope:
{
"error": {
"code": "validation_failed",
"message": "One or more fields are invalid.",
"requestId": "req_example",
"retryable": false,
"details": [
{
"field": "supportUrl",
"code": "invalid_url",
"message": "Provide a valid support URL."
}
]
}
}
| HTTP | Code or meaning | Use |
|---|---|---|
| 400 | invalid_query | Malformed input, unsupported query, selector, or cursor. |
| 401 | unauthorized | Missing or invalid facade API key. |
| 403 | forbidden / upstream_forbidden | Caller permission or configured Apple key does not allow the read. |
| 404 | resource_not_found | Resource or exact locale is absent or outside the caller’s scope. |
| 409 | Conflict | Ambiguous selection, duplicate resource, incompatible state, or idempotency conflict. |
| 422 | validation_failed | Recognized request has invalid fields or an Apple validation failure. |
| 429 | rate_limited | Facade or Apple limit; respect Retry-After when present. |
| 503 | hosted_connections_not_configured | Hosted connection storage or encryption configuration is missing; other service availability failures may also use this status. |
| 502 / 504 | Upstream failure | Rejected Apple credentials, invalid upstream payload, or timeout. These are not empty results. |
Each response includes a request ID. Error details use facade field names and sanitized messages; credentials and private Apple response bodies are not returned.
Rollout
Core reads, hosted connection setup/revocation, and explicit selection are implemented. Known Apple resource routes accept GET only; mutation methods return 405 method_not_allowed. Read-parity endpoints such as builds, users, and bundle IDs come later; reports and multi-step copy workflows are separate milestones. Each endpoint page labels implementation status separately from its delivery stage. Consult the GET reference or implemented-route OpenAPI for coverage.