openapi: 3.0.3 info: title: Apple CloudKit Web Services API description: | CloudKit web services provides an HTTP interface to fetch, create, update, and delete records, zones, and subscriptions. You also have access to discoverable users and contacts. ## Authentication There are two authentication methods: 1. API Token Authentication - Use query parameters: `?ckAPIToken=[API token]&ckWebAuthToken=[Web Auth Token]` 2. Server-to-Server Key Authentication - Pass the key ID as `X-Apple-CloudKit-Request-KeyID` header ## Base URL Structure `https://api.apple-cloudkit.com/database/{version}/{container}/{environment}/{database}/{operation}` Where: - version: Protocol version (currently "1") - container: Unique identifier for the app's container (begins with "iCloud.") - environment: "development" or "production" - database: "public", "private", or "shared" version: 1.0.0 contact: name: Apple Developer Support url: https://developer.apple.com/support/ servers: - url: https://api.apple-cloudkit.com description: CloudKit Web Services API security: - ApiTokenAuth: [] - ServerToServerAuth: [] paths: /database/{version}/{container}/{environment}/{database}/records/query: post: summary: Query Records description: Fetch records using a query with filters and sorting options operationId: queryRecords tags: - Records parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: zoneID: $ref: '#/components/schemas/ZoneID' resultsLimit: type: integer description: Maximum number of records to return query: $ref: '#/components/schemas/Query' desiredKeys: type: array items: type: string description: List of field names to return continuationMarker: type: string description: Marker for pagination zoneWide: type: boolean description: >- If true, query across all zones rather than a single zone. numbersAsStrings: type: boolean description: >- If true, return numeric field values as strings to avoid JavaScript precision loss (relevant for INT64). responses: '200': description: Successful query content: application/json: schema: $ref: '#/components/schemas/QueryResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' '403': $ref: '#/components/responses/Failure' '404': $ref: '#/components/responses/Failure' '409': $ref: '#/components/responses/Failure' '412': $ref: '#/components/responses/Failure' '413': $ref: '#/components/responses/Failure' '429': $ref: '#/components/responses/Failure' '421': $ref: '#/components/responses/Failure' '500': $ref: '#/components/responses/Failure' '503': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/records/modify: post: summary: Modify Records description: Create, update, or delete records (supports bulk operations) operationId: modifyRecords tags: - Records parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: operations: type: array items: $ref: '#/components/schemas/RecordOperation' atomic: type: boolean description: If true, all operations must succeed or all fail zoneID: $ref: '#/components/schemas/ZoneID' desiredKeys: type: array items: type: string description: >- List of field names to limit the fields returned in the modify response. numbersAsStrings: type: boolean description: >- If true, return numeric field values as strings to avoid JavaScript precision loss (relevant for INT64). responses: '200': description: Records modified successfully content: application/json: schema: $ref: '#/components/schemas/ModifyResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' '403': $ref: '#/components/responses/Failure' '404': $ref: '#/components/responses/Failure' '409': $ref: '#/components/responses/Failure' '412': $ref: '#/components/responses/Failure' '413': $ref: '#/components/responses/Failure' '429': $ref: '#/components/responses/Failure' '421': $ref: '#/components/responses/Failure' '500': $ref: '#/components/responses/Failure' '503': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/records/lookup: post: summary: Lookup Records description: Fetch specific records by their IDs operationId: lookupRecords tags: - Records parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: records: type: array items: type: object properties: recordName: type: string desiredKeys: type: array items: type: string responses: '200': description: Records retrieved successfully content: application/json: schema: $ref: '#/components/schemas/LookupResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' '403': $ref: '#/components/responses/Failure' '404': $ref: '#/components/responses/Failure' '409': $ref: '#/components/responses/Failure' '412': $ref: '#/components/responses/Failure' '413': $ref: '#/components/responses/Failure' '429': $ref: '#/components/responses/Failure' '421': $ref: '#/components/responses/Failure' '500': $ref: '#/components/responses/Failure' '503': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/records/resolve: post: summary: Fetch Record Information description: | Resolve one or more share short GUIDs into information about the shared records they identify — the root record, the `cloudKit.share` record, the owner identity, and the caller's participation in each share. Routed against the public database with web-auth credentials (user-context auth): Apple's reference documents the path with a fixed `public` database scope, and the operation resolves shares on behalf of the *current* user. Documented in Apple's archived CloudKit Web Services Reference (`FetchingRecordInformation`); absent from the current online docs. operationId: resolveShortGUIDs tags: - Records parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: shortGUIDs: type: array description: The short GUIDs identifying the shares to resolve. items: $ref: '#/components/schemas/ShortGUID' required: - shortGUIDs responses: '200': description: Short GUIDs resolved successfully. content: application/json: schema: $ref: '#/components/schemas/ShortGUIDResultResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' '403': $ref: '#/components/responses/Failure' '404': $ref: '#/components/responses/Failure' '409': $ref: '#/components/responses/Failure' '412': $ref: '#/components/responses/Failure' '413': $ref: '#/components/responses/Failure' '429': $ref: '#/components/responses/Failure' '421': $ref: '#/components/responses/Failure' '500': $ref: '#/components/responses/Failure' '503': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/records/accept: post: summary: Accept Share Records description: | Accept one or more shares — each identified by a short GUID — on behalf of the current user. The response mirrors `records/resolve`, reporting the caller's participation status for each accepted share. Routed against the public database with web-auth credentials (user-context auth): Apple's reference documents the path with a fixed `public` database scope, and there is no current user to accept on behalf of without web-auth. Documented in Apple's archived CloudKit Web Services Reference (`AcceptingShareRecords`); absent from the current online docs. operationId: acceptShares tags: - Records parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: shortGUIDs: type: array description: The short GUIDs identifying the shares to accept. items: $ref: '#/components/schemas/ShortGUID' required: - shortGUIDs responses: '200': description: Shares accepted successfully. content: application/json: schema: $ref: '#/components/schemas/ShortGUIDResultResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' '403': $ref: '#/components/responses/Failure' '404': $ref: '#/components/responses/Failure' '409': $ref: '#/components/responses/Failure' '412': $ref: '#/components/responses/Failure' '413': $ref: '#/components/responses/Failure' '429': $ref: '#/components/responses/Failure' '421': $ref: '#/components/responses/Failure' '500': $ref: '#/components/responses/Failure' '503': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/records/changes: post: summary: Fetch Record Changes description: Get all record changes relative to a sync token operationId: fetchRecordChanges tags: - Records parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: zoneID: $ref: '#/components/schemas/ZoneID' syncToken: type: string description: Token from previous sync operation resultsLimit: type: integer desiredKeys: type: array items: type: string description: >- List of field names to limit the fields returned per changed record. desiredRecordTypes: type: array items: type: string description: >- List of record-type names to limit the change feed to specific record types. responses: '200': description: Changes retrieved successfully content: application/json: schema: $ref: '#/components/schemas/ChangesResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' '403': $ref: '#/components/responses/Failure' '404': $ref: '#/components/responses/Failure' '409': $ref: '#/components/responses/Failure' '412': $ref: '#/components/responses/Failure' '413': $ref: '#/components/responses/Failure' '429': $ref: '#/components/responses/Failure' '421': $ref: '#/components/responses/Failure' '500': $ref: '#/components/responses/Failure' '503': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/zones/list: get: summary: List All Zones description: Fetch all zones in the database operationId: listZones tags: - Zones parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' responses: '200': description: Zones retrieved successfully content: application/json: schema: $ref: '#/components/schemas/ZonesListResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' '403': $ref: '#/components/responses/Failure' '404': $ref: '#/components/responses/Failure' '409': $ref: '#/components/responses/Failure' '412': $ref: '#/components/responses/Failure' '413': $ref: '#/components/responses/Failure' '429': $ref: '#/components/responses/Failure' '421': $ref: '#/components/responses/Failure' '500': $ref: '#/components/responses/Failure' '503': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/zones/lookup: post: summary: Lookup Zones description: Fetch specific zones by their IDs operationId: lookupZones tags: - Zones parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: zones: type: array items: $ref: '#/components/schemas/ZoneID' responses: '200': description: Zones retrieved successfully content: application/json: schema: $ref: '#/components/schemas/ZonesLookupResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/zones/modify: post: summary: Modify Zones description: Create or delete zones (only supported in private database) operationId: modifyZones tags: - Zones parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: operations: type: array items: $ref: '#/components/schemas/ZoneOperation' responses: '200': description: Zones modified successfully content: application/json: schema: $ref: '#/components/schemas/ZonesModifyResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/zones/changes: post: summary: Fetch Zone Changes (deprecated) description: >- Get all changed zones relative to a meta-sync token. **Deprecated by Apple** in favor of `changes/database` (`fetchDatabaseChanges`), which returns the same "which zones changed" information. New code should use `changes/database`. operationId: fetchZoneChanges deprecated: true tags: - Zones parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: metaSyncToken: type: string description: >- The `metaSyncToken` returned by a previous `zones/changes` response. Omit it to fetch every zone. Verified against a live container (issue #430): this operation reads and returns `metaSyncToken`, not `syncToken`. A request sending `syncToken` is silently ignored and replays the first page. Apple's archived reference names the key `metaSyncToken` as well; only one line of its `moreComing` prose calls it `syncToken`. This is specific to `zones/changes` — `changes/database`, `changes/zone` and `records/changes` all use `syncToken`. responses: '200': description: Zone changes retrieved successfully content: application/json: schema: $ref: '#/components/schemas/ZoneChangesResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/changes/database: post: summary: Fetch Database Changes description: >- Get the record zones in the database that have changed relative to a sync token. This is the current replacement for the deprecated `zones/changes` operation. Follow up with `changes/zone` to fetch the record changes within each returned zone. operationId: fetchDatabaseChanges tags: - Zones parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: syncToken: type: string description: >- Identifies a point in the database's change history. Omit on the initial fetch to start from the beginning. resultsLimit: type: integer description: >- The maximum number of zone changes to fetch. Defaults to the maximum allowed in a request. responses: '200': description: Database changes retrieved successfully content: application/json: schema: $ref: '#/components/schemas/DatabaseChangesResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' '403': $ref: '#/components/responses/Failure' '404': $ref: '#/components/responses/Failure' '409': $ref: '#/components/responses/Failure' '412': $ref: '#/components/responses/Failure' '413': $ref: '#/components/responses/Failure' '429': $ref: '#/components/responses/Failure' '421': $ref: '#/components/responses/Failure' '500': $ref: '#/components/responses/Failure' '503': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/changes/zone: post: summary: Fetch Record Zone Changes description: >- Get the records that changed within one or more record zones relative to each zone's sync token. Intended for custom zones. Each entry in the response `zones` array is either a per-zone success result or a per-zone error. operationId: fetchRecordZoneChanges tags: - Zones parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object required: - zones properties: zones: type: array description: >- A zone request dictionary for each zone to fetch record changes from. Per-zone values override the top-level values in this request. items: $ref: '#/components/schemas/RecordZoneChangesRequestZone' reverse: type: boolean description: >- Whether the changes are returned in reverse order. desiredKeys: type: array items: type: string description: >- Record field names limiting the fields returned per changed record. Omit to fetch all fields. numberAsStrings: type: boolean description: >- Whether number fields should be represented as strings. Defaults to `false`. resultsLimit: type: integer description: >- The maximum number of records to fetch. Defaults to the maximum allowed in a request. desiredRecordTypes: type: array items: type: string description: >- Record-type names limiting the change feed to specific record types. Omit to fetch changes from all record types. responses: '200': description: Record zone changes retrieved successfully content: application/json: schema: $ref: '#/components/schemas/RecordZoneChangesResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' '403': $ref: '#/components/responses/Failure' '404': $ref: '#/components/responses/Failure' '409': $ref: '#/components/responses/Failure' '412': $ref: '#/components/responses/Failure' '413': $ref: '#/components/responses/Failure' '429': $ref: '#/components/responses/Failure' '421': $ref: '#/components/responses/Failure' '500': $ref: '#/components/responses/Failure' '503': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/subscriptions/list: get: summary: List All Subscriptions description: Fetch all subscriptions in the database operationId: listSubscriptions tags: - Subscriptions parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' responses: '200': description: Subscriptions retrieved successfully content: application/json: schema: $ref: '#/components/schemas/SubscriptionsListResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/subscriptions/lookup: post: summary: Lookup Subscriptions description: Fetch specific subscriptions by their IDs operationId: lookupSubscriptions tags: - Subscriptions parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: subscriptions: type: array items: type: object properties: subscriptionID: type: string responses: '200': description: Subscriptions retrieved successfully content: application/json: schema: $ref: '#/components/schemas/SubscriptionsLookupResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/subscriptions/modify: post: summary: Modify Subscriptions description: Create, update, or delete subscriptions operationId: modifySubscriptions tags: - Subscriptions parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: operations: type: array items: $ref: '#/components/schemas/SubscriptionOperation' responses: '200': description: Subscriptions modified successfully content: application/json: schema: $ref: '#/components/schemas/SubscriptionsModifyResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/users/caller: get: summary: Get the Caller (Current User) description: | Fetch the authenticated caller's user information. This replaces the deprecated `users/current` endpoint. Requires public database with a web-auth token (user-context auth); server-to-server credentials and the private database will be rejected with `BAD_REQUEST: endpoint not applicable in the database type`. operationId: getCaller tags: - Users parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' responses: '200': description: User information retrieved successfully content: application/json: schema: $ref: '#/components/schemas/UserResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' '403': $ref: '#/components/responses/Failure' '404': $ref: '#/components/responses/Failure' '409': $ref: '#/components/responses/Failure' '412': $ref: '#/components/responses/Failure' '413': $ref: '#/components/responses/Failure' '429': $ref: '#/components/responses/Failure' '421': $ref: '#/components/responses/Failure' '500': $ref: '#/components/responses/Failure' '503': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/users/discover: post: summary: Discover User Identities description: Discover all user identities based on email addresses or user record names operationId: discoverUserIdentities tags: - Users parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: lookupInfos: type: array items: type: object properties: emailAddress: type: string phoneNumber: type: string userRecordName: type: string responses: '200': description: User identities discovered successfully content: application/json: schema: $ref: '#/components/schemas/DiscoverResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' # GET /users/discover — see #28 get: summary: Discover All User Identities description: | Fetch every user identity in the caller's CloudKit address book. Requires public-database routing with web-auth credentials (user-context auth); only users who have run the app and granted discoverability are returned. operationId: discoverAllUserIdentities tags: - Users parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' responses: '200': description: All discoverable user identities returned successfully content: application/json: schema: $ref: '#/components/schemas/DiscoverResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/users/lookup/email: post: summary: Lookup Users by Email description: | Look up user identities by email address. Requires public-database routing with web-auth credentials (user-context auth). Each requested email returns at most one identity in the `users` array. operationId: lookupUsersByEmail tags: - Users parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: users: type: array items: type: object properties: emailAddress: type: string responses: '200': description: User identities returned successfully content: application/json: schema: $ref: '#/components/schemas/DiscoverResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/users/lookup/id: post: summary: Lookup Users by Record Name description: | Look up user identities by record name (CloudKit user record ID). Requires public-database routing with web-auth credentials. operationId: lookupUsersByRecordName tags: - Users parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: users: type: array items: type: object properties: userRecordName: type: string responses: '200': description: User identities returned successfully content: application/json: schema: $ref: '#/components/schemas/DiscoverResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/users/lookup/contacts: post: summary: Lookup Contacts (Deprecated) description: Fetch contacts (This endpoint is deprecated) deprecated: true operationId: lookupContacts tags: - Users parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: contacts: type: array items: type: object responses: '200': description: Contacts retrieved successfully content: application/json: schema: $ref: '#/components/schemas/ContactsResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/assets/upload: post: summary: Request Asset Upload URLs description: | Request upload URLs for asset fields. This is the first step in a two-step process: 1. Request upload URLs by specifying the record type and field name 2. Upload the actual binary data to the returned URL (separate HTTP request) Upload URLs are valid for 15 minutes. Maximum file size is 15 MB. operationId: uploadAssets tags: - Assets parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: zoneID: $ref: '#/components/schemas/ZoneID' description: Optional zone ID. Defaults to default zone if not specified. tokens: type: array description: Array of asset fields to request upload URLs for items: type: object required: - recordType - fieldName properties: recordName: type: string description: Unique name to identify the record. Defaults to random UUID if not specified. recordType: type: string description: Name of the record type fieldName: type: string description: Name of the Asset or Asset list field required: - tokens responses: '200': description: Upload URLs returned successfully content: application/json: schema: $ref: '#/components/schemas/AssetUploadResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /database/{version}/{container}/{environment}/{database}/assets/rereference: post: summary: Re-reference Existing Assets description: | Fetch reusable asset descriptors for assets that already live on other records, without re-uploading the bytes. Each returned descriptor can be set on another record's Asset field via `records/modify` to share the same underlying asset. Assets are deleted only when all references to them are removed. Documented in Apple's archived CloudKit Web Services Reference (`RereferenceAssets`); absent from the current online docs. operationId: rereferenceAssets tags: - Assets parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' - $ref: '#/components/parameters/database' requestBody: required: true content: application/json: schema: type: object properties: zoneID: $ref: '#/components/schemas/ZoneID' description: Optional zone ID. Defaults to default zone if not specified. assets: type: array description: Array of source asset fields to re-reference. items: type: object required: - recordName - fieldName properties: recordName: type: string description: Name of the record holding the source asset. fieldName: type: string description: Name of the Asset field on the source record. required: - assets responses: '200': description: Reusable asset descriptors returned successfully. content: application/json: schema: $ref: '#/components/schemas/AssetRereferenceResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /device/{version}/{container}/{environment}/tokens/create: post: summary: Create APNs Token description: | Create an Apple Push Notification service (APNs) token. Lives under the `/device/` API module (not `/database/`). CloudKit's archived REST reference documents this under `/database/...`, but the live service routes only OPTIONS to that path and returns `405 Method Not Allowed` for POST. The working path is the one CloudKit JS uses (`setApiModuleName("device")`). operationId: createToken tags: - Tokens parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' requestBody: required: true content: application/json: schema: type: object required: - apnsEnvironment - clientId properties: apnsEnvironment: type: string enum: [development, production] clientId: type: string description: | Logical CloudKit client identifier. CloudKit JS persists this across sessions for push de-dup; for server-side callers a fresh UUID per request is fine unless continuity matters. responses: '200': description: Token created successfully content: application/json: schema: $ref: '#/components/schemas/TokenResponse' '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' /device/{version}/{container}/{environment}/tokens/register: post: summary: Register Token description: | Register an APNs device token for push notifications. Lives under the `/device/` API module (not `/database/`) — same rationale as `tokens/create`. operationId: registerToken tags: - Tokens parameters: - $ref: '#/components/parameters/version' - $ref: '#/components/parameters/container' - $ref: '#/components/parameters/environment' requestBody: required: true content: application/json: schema: type: object required: - apnsEnvironment - apnsToken - clientId properties: apnsEnvironment: type: string enum: [development, production] description: The APNs environment the token targets. apnsToken: type: string description: The APNs token to register clientId: type: string description: | Logical CloudKit client identifier. Reuse the value used with `tokens/create` to keep both calls tied to the same logical client. responses: '200': description: Token registered successfully '400': $ref: '#/components/responses/Failure' '401': $ref: '#/components/responses/Failure' components: securitySchemes: ApiTokenAuth: type: apiKey in: query name: ckAPIToken description: API token created using CloudKit Dashboard ServerToServerAuth: type: apiKey in: header name: X-Apple-CloudKit-Request-KeyID description: Key ID for server-to-server authentication parameters: version: name: version in: path required: true schema: type: string default: "1" description: Protocol version container: name: container in: path required: true schema: type: string description: Container ID (begins with "iCloud.") environment: name: environment in: path required: true schema: type: string enum: [development, production] description: Container environment database: name: database in: path required: true schema: type: string enum: [public, private, shared] description: Database scope schemas: ZoneID: type: object properties: zoneName: type: string ownerName: type: string Filter: type: object properties: comparator: type: string enum: [EQUALS, NOT_EQUALS, LESS_THAN, LESS_THAN_OR_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUALS, NEAR, CONTAINS_ALL_TOKENS, IN, NOT_IN, CONTAINS_ANY_TOKENS, LIST_CONTAINS, NOT_LIST_CONTAINS, BEGINS_WITH, NOT_BEGINS_WITH, LIST_MEMBER_BEGINS_WITH, NOT_LIST_MEMBER_BEGINS_WITH] fieldName: type: string fieldValue: $ref: '#/components/schemas/FieldValueRequest' Sort: type: object properties: fieldName: type: string ascending: type: boolean Query: type: object description: A record query, shared by records/query and query subscriptions properties: recordType: type: string description: The record type to query filterBy: type: array items: $ref: '#/components/schemas/Filter' sortBy: type: array items: $ref: '#/components/schemas/Sort' RecordOperation: type: object properties: operationType: type: string enum: [create, update, forceUpdate, replace, forceReplace, delete, forceDelete] record: $ref: '#/components/schemas/RecordRequest' RecordRequest: type: object description: Record schema for API requests (fields use FieldValueRequest) properties: recordName: type: string description: The unique identifier for the record recordType: type: string description: The record type (schema name) recordChangeTag: type: string description: Change tag for optimistic concurrency control fields: type: object description: Record fields with their values (no type metadata) additionalProperties: $ref: '#/components/schemas/FieldValueRequest' createShortGUID: type: boolean description: | Whether to create a short GUID so this record can be shared. The response echoes the generated GUID back as `shortGUID`. forRecord: $ref: '#/components/schemas/ShareTargetReference' publicPermission: type: string enum: [NONE, READ_ONLY, READ_WRITE, UNKNOWN] description: | The public read/write permissions to apply. Set when creating a `cloudKit.share` record. participants: type: array description: | The participants to invite. Set when creating a `cloudKit.share` record. items: $ref: '#/components/schemas/ShareParticipant' ShareTargetReference: type: object description: | Identifies the record being shared when creating a `cloudKit.share` record (the `forRecord` key). properties: recordName: type: string recordChangeTag: type: string required: - recordName RecordResponse: type: object description: Record schema for API responses (fields use FieldValueResponse) properties: recordName: type: string description: The unique identifier for the record recordType: type: string description: The record type (schema name) recordChangeTag: type: string description: Change tag for optimistic concurrency control fields: type: object description: Record fields with their values and optional type information additionalProperties: $ref: '#/components/schemas/FieldValueResponse' created: $ref: '#/components/schemas/RecordTimestamp' modified: $ref: '#/components/schemas/RecordTimestamp' deleted: type: boolean description: Whether the record was deleted shortGUID: type: string description: | The short GUID of a shared record. Present only on records that have been shared (see `createShortGUID` on the request side). share: $ref: '#/components/schemas/ShareReference' publicPermission: type: string enum: [NONE, READ_ONLY, READ_WRITE, UNKNOWN] description: | The public read/write permissions of a shared record. Present on `cloudKit.share` records. participants: type: array description: | The participants in a shared record. Present on `cloudKit.share` records. items: $ref: '#/components/schemas/ShareParticipant' owner: $ref: '#/components/schemas/ShareParticipant' currentUserParticipant: $ref: '#/components/schemas/ShareParticipant' ShareReference: type: object description: | A reference to the `cloudKit.share` record governing a shared record. properties: recordName: type: string FieldValueRequest: type: object description: | A CloudKit field value for API requests. The type field is optional. It is required for the scalar types whose JSON representation is otherwise ambiguous (TIMESTAMP, BYTES, DOUBLE) and for the IN/NOT_IN list filters (the *_LIST types specify the list element type). properties: value: oneOf: - $ref: '#/components/schemas/StringValue' - $ref: '#/components/schemas/Int64Value' - $ref: '#/components/schemas/DoubleValue' - $ref: '#/components/schemas/BytesValue' - $ref: '#/components/schemas/DateValue' - $ref: '#/components/schemas/LocationValue' - $ref: '#/components/schemas/ReferenceValue' - $ref: '#/components/schemas/AssetValue' - $ref: '#/components/schemas/ListValue' type: type: string enum: [STRING, INT64, DOUBLE, BYTES, TIMESTAMP, REFERENCE, ASSET, ASSETID, LOCATION, STRING_LIST, INT64_LIST, DOUBLE_LIST, BYTES_LIST, TIMESTAMP_LIST, REFERENCE_LIST, LOCATION_LIST, ASSET_LIST] description: | Optional CloudKit field type. Sent for scalar values whose JSON form is ambiguous (e.g. "TIMESTAMP", "BYTES", "DOUBLE") so CloudKit does not infer the wrong type, and for IN/NOT_IN list filters (e.g. "INT64_LIST"). required: - value FieldValueResponse: type: object description: | A CloudKit field value from API responses. May include optional type field for explicit type information. properties: value: oneOf: - $ref: '#/components/schemas/StringValue' - $ref: '#/components/schemas/Int64Value' - $ref: '#/components/schemas/DoubleValue' - $ref: '#/components/schemas/BytesValue' - $ref: '#/components/schemas/DateValue' - $ref: '#/components/schemas/LocationValue' - $ref: '#/components/schemas/ReferenceValue' - $ref: '#/components/schemas/AssetValue' - $ref: '#/components/schemas/ListValue' type: type: string enum: [STRING, INT64, DOUBLE, BYTES, REFERENCE, ASSET, ASSETID, LOCATION, TIMESTAMP, LIST] description: The CloudKit field type (optional, may be inferred from value) required: - value StringValue: type: string description: A text string value Int64Value: type: integer format: int64 description: A 64-bit integer value DoubleValue: type: number format: double description: A double-precision floating point value BytesValue: type: string description: Base64-encoded string representing binary data DateValue: type: number format: double description: Number representing milliseconds since epoch (January 1, 1970) LocationValue: type: object description: Location dictionary as defined in CloudKit Web Services required: - latitude - longitude properties: latitude: type: number format: double description: Latitude in degrees longitude: type: number format: double description: Longitude in degrees horizontalAccuracy: type: number format: double description: Horizontal accuracy in meters verticalAccuracy: type: number format: double description: Vertical accuracy in meters altitude: type: number format: double description: Altitude in meters speed: type: number format: double description: Speed in meters per second course: type: number format: double description: Course in degrees timestamp: type: number format: double description: Timestamp in milliseconds since epoch ReferenceValue: type: object description: Reference dictionary as defined in CloudKit Web Services required: - recordName properties: recordName: type: string description: The record name being referenced action: type: string enum: [NONE, DELETE_SELF] description: Action to perform on the referenced record AssetValue: type: object description: Asset dictionary as defined in CloudKit Web Services properties: fileChecksum: type: string description: Checksum of the asset file size: type: integer format: int64 description: Size of the asset in bytes referenceChecksum: type: string description: Checksum of the asset reference wrappingKey: type: string description: Wrapping key for the asset receipt: type: string description: Receipt for the asset downloadURL: type: string format: uri description: URL for downloading the asset ListValue: type: array description: Array containing any of the above field types items: oneOf: - $ref: '#/components/schemas/StringValue' - $ref: '#/components/schemas/Int64Value' - $ref: '#/components/schemas/DoubleValue' - $ref: '#/components/schemas/BytesValue' - $ref: '#/components/schemas/DateValue' - $ref: '#/components/schemas/LocationValue' - $ref: '#/components/schemas/ReferenceValue' - $ref: '#/components/schemas/AssetValue' - $ref: '#/components/schemas/ListValue' ZoneOperation: type: object properties: operationType: type: string enum: [create, delete] zone: type: object properties: zoneID: $ref: '#/components/schemas/ZoneID' SubscriptionOperation: type: object properties: operationType: type: string enum: [create, update, delete] subscription: $ref: '#/components/schemas/Subscription' Subscription: type: object description: > A CloudKit subscription — a persistent server-side trigger that produces push notifications when matching changes occur. Mirrors `CloudKit.Subscription` from the CloudKit JS reference. properties: subscriptionID: type: string description: Caller-supplied unique identifier for the subscription. subscriptionType: type: string enum: [query, zone] query: $ref: '#/components/schemas/Query' description: > For `subscriptionType: query`, the watched query (`recordType` + filters + sort). zoneID: $ref: '#/components/schemas/ZoneID' description: > For `subscriptionType: zone`, the watched record zone. zoneWide: type: boolean description: > Zone subscriptions only. If `true`, the subscription watches *every zone* in the database (the wire representation of a native `CKDatabaseSubscription`); if `false`/absent, only the zone identified by `zoneID` is watched. Only valid against private and shared databases. Default `false`. firesOn: type: array items: type: string enum: [create, update, delete] description: > The record-change events that trigger a push (e.g. `[create, update]`). CloudKit treats the exact set as the subscription's uniqueness key — two subscriptions on the same `(recordType, firesOn)` tuple collide regardless of `subscriptionID`. firesOnce: type: boolean description: > If `true`, the subscription is destroyed after producing its first notification. Default `false`. notificationInfo: $ref: '#/components/schemas/NotificationInfo' description: > How the system should alert the user when the subscription fires. Optional. NotificationInfo: type: object description: > How CloudKit shapes the push notification produced by a subscription. Mirrors `CloudKit.NotificationInfo` from the CloudKit JS reference. properties: alertBody: type: string description: The text of the alert message. alertLocalizationKey: type: string description: A key to a localized alert message. alertLocalizationArgs: type: array items: type: string description: > Strings that appear as variables if `alertLocalizationKey` is a format specifier. alertActionLocalizationKey: type: string description: A key to the localized title of the alert's action button. alertLaunchImage: type: string description: The filename of the image to use as the launch image. soundName: type: string description: The filename of the sound to play when the notification arrives. shouldBadge: type: boolean description: > Whether the app icon's badge should be incremented. Default `false`. shouldSendContentAvailable: type: boolean description: > Whether the notification should mark new content as available (silent background fetch). Default `false`. additionalFields: type: array items: type: string description: > Names of record fields whose values should be included in the notification payload. category: type: string description: The notification category (UN actionable category identifier). QueryResponse: type: object properties: records: type: array items: $ref: '#/components/schemas/RecordResponse' continuationMarker: type: string ModifyResponse: type: object properties: records: type: array items: oneOf: - $ref: '#/components/schemas/RecordOperationFailure' - $ref: '#/components/schemas/RecordResponse' LookupResponse: type: object properties: records: type: array items: oneOf: - $ref: '#/components/schemas/RecordOperationFailure' - $ref: '#/components/schemas/RecordResponse' ChangesResponse: type: object properties: records: type: array items: $ref: '#/components/schemas/RecordResponse' syncToken: type: string moreComing: type: boolean Zone: type: object description: > A record zone as returned by the zone endpoints (`zones/list`, `zones/lookup`, `zones/modify`, `zones/changes`). Matches the "Zone Dictionary" in Apple's archived CloudKit Web Services Reference, which documents exactly three keys: `zoneID`, `syncToken`, and `atomic`. `isEager` is deliberately absent — it appears in no primary Apple source (see issue #386). properties: zoneID: $ref: '#/components/schemas/ZoneID' syncToken: type: string description: The current point in the zone's change history. atomic: type: boolean description: > A Boolean value indicating whether this zone supports atomic operations. ZonesListResponse: type: object properties: zones: type: array items: $ref: '#/components/schemas/Zone' ZonesLookupResponse: type: object properties: zones: type: array items: $ref: '#/components/schemas/Zone' ZonesModifyResponse: type: object description: | Response body of `zones/modify`. Each entry in `zones` is either a Zone dictionary (success) or a Zone Fetch Error dictionary (failure), per Apple's archived reference. `zones/modify` is a batch endpoint whose realistic failure mode is partial — creating a zone that already exists alongside zones that create cleanly — so a failed entry must not discard the entries that succeeded (see issue #431). properties: zones: type: array items: oneOf: - $ref: '#/components/schemas/ZoneFetchFailure' - $ref: '#/components/schemas/Zone' ZoneChangesResponse: type: object description: | Response body of the deprecated `zones/changes` operation. Its token key is `metaSyncToken`: a live container returned exactly `[moreComing, metaSyncToken, zones]` at the top level, with no `syncToken` (issue #430). The other change-tracking operations (`changes/database`, `changes/zone`, `records/changes`) use `syncToken`. properties: zones: type: array items: $ref: '#/components/schemas/Zone' metaSyncToken: type: string description: >- Identifies a point in the database's change history. Send it back as `metaSyncToken` on the next request to fetch only newer changes. moreComing: type: boolean DatabaseChangesResponse: type: object description: | Response body of `changes/database` (Fetching Database Changes). Each entry in `zones` is either a Zone dictionary (success) or a Zone Fetch Error dictionary (failure), per Apple's reference. properties: zones: type: array items: oneOf: - $ref: '#/components/schemas/ZoneFetchFailure' - $ref: '#/components/schemas/DatabaseChangedZone' syncToken: type: string description: >- Identifies a point in the database's change history. Pass this in the next request to fetch only newer changes. moreComing: type: boolean description: >- Whether there are more changes to request using the returned `syncToken`. DatabaseChangedZone: type: object description: A zone that changed, as returned by `changes/database`. properties: zoneID: $ref: '#/components/schemas/ZoneID' ZoneFetchFailure: type: object description: | Per-zone error returned inline in the `zones` array of a 200 zone response (`changes/database`, `changes/zone`, `zones/modify`). Mirrors `RecordOperationFailure` for records, but keyed by `zoneID`. required: - serverErrorCode properties: zoneID: $ref: '#/components/schemas/ZoneID' serverErrorCode: $ref: '#/components/schemas/OperationFailureServerErrorCode' reason: type: string description: A string indicating the reason for the error. retryAfter: type: integer description: Suggested seconds to wait before retrying. Absent if not retryable. uuid: type: string description: A unique identifier for this error. redirectURL: type: string description: Redirect URL for sign-in; present when serverErrorCode is AUTHENTICATION_REQUIRED. RecordZoneChangesRequestZone: type: object description: | A per-zone request entry in the `zones` array of a `changes/zone` request. Carries the same tuning keys as the enclosing request; values set here override the top-level values for this zone. required: - zoneID properties: zoneID: $ref: '#/components/schemas/ZoneID' syncToken: type: string description: >- Identifies a point in this zone's change history. Omit on the initial fetch. reverse: type: boolean description: Whether the changes are returned in reverse order. desiredKeys: type: array items: type: string description: Record field names limiting the fields returned per changed record. numberAsStrings: type: boolean description: Whether number fields should be represented as strings. resultsLimit: type: integer description: The maximum number of records to fetch for this zone. desiredRecordTypes: type: array items: type: string description: Record-type names limiting the change feed for this zone. RecordZoneChangesResponse: type: object description: | Response body of `changes/zone` (Fetching Record Zone Changes). Each entry in `zones` is either a Zone Record Fetch dictionary (success) or a Zone Record Fetch Error dictionary (failure), per Apple's reference. properties: zones: type: array items: oneOf: - $ref: '#/components/schemas/ZoneFetchFailure' - $ref: '#/components/schemas/RecordZoneChangesZoneResult' RecordZoneChangesZoneResult: type: object description: >- A successful per-zone result of `changes/zone`: the records that changed in that zone plus that zone's own sync token and `moreComing` flag. properties: zoneID: $ref: '#/components/schemas/ZoneID' records: type: array items: $ref: '#/components/schemas/RecordResponse' syncToken: type: string description: Identifies a point in this zone's change history. moreComing: type: boolean description: >- Whether there are more changes to request for this zone using the returned `syncToken`. SubscriptionsListResponse: type: object properties: subscriptions: type: array items: $ref: '#/components/schemas/Subscription' SubscriptionsLookupResponse: type: object properties: subscriptions: type: array items: $ref: '#/components/schemas/Subscription' SubscriptionOperationFailure: description: | Per-subscription error returned inline in the `subscriptions` array of a 200 modify response. Identifies the subscription that failed and why. Mirrors `RecordOperationFailure` for records. Distinct from `ErrorResponse`, which is the body of a top-level 4xx/5xx HTTP failure. allOf: - $ref: '#/components/schemas/OperationFailureCommon' - type: object required: - subscriptionID properties: subscriptionID: type: string description: The identifier of the subscription the operation failed on. SubscriptionsModifyResponse: type: object properties: subscriptions: type: array items: oneOf: - $ref: '#/components/schemas/SubscriptionOperationFailure' - $ref: '#/components/schemas/Subscription' RecordTimestamp: type: object description: Timestamp information for record creation or modification properties: timestamp: type: number description: Unix timestamp in milliseconds userRecordName: type: string description: Record name of the user who performed the action NameComponents: type: object description: The parts of a user's name properties: namePrefix: type: string description: The user's name prefix givenName: type: string description: The user's first name middleName: type: string description: The user's middle name familyName: type: string description: The user's last name nameSuffix: type: string description: The user's name suffix nickname: type: string description: The user's nickname phoneticRepresentation: type: string description: A phonetic representation of the user's name UserIdentityLookupInfo: type: object description: Information used to look up a user identity properties: emailAddress: type: string description: The user's email address phoneNumber: type: string description: The user's phone number userRecordName: type: string description: The record name of the user UserIdentity: type: object description: A user identity returned by discover endpoints properties: userRecordName: type: string description: The record name of the user nameComponents: $ref: '#/components/schemas/NameComponents' lookupInfo: $ref: '#/components/schemas/UserIdentityLookupInfo' UserResponse: type: object description: A user returned by current/lookup endpoints (User Dictionary) properties: userRecordName: type: string firstName: type: string lastName: type: string emailAddress: type: string DiscoverResponse: type: object properties: users: type: array items: $ref: '#/components/schemas/UserIdentity' ShortGUID: type: object description: | A short global identifier for a shared record, used to resolve (`records/resolve`) and accept (`records/accept`) shares. properties: value: type: string description: The value of the short global ID. shouldFetchRootRecord: type: boolean description: | Whether the root record should be fetched alongside the share. rootRecordDesiredKeys: type: array description: | Field names limiting the data returned in the root record. When omitted, every field of the root record is returned. items: type: string required: - value ShareParticipant: type: object description: A participant in a shared record. properties: userIdentity: $ref: '#/components/schemas/UserIdentity' permission: type: string enum: [NONE, READ_ONLY, READ_WRITE, UNKNOWN] description: The participant's read and write permissions. type: type: string enum: [OWNER, ADMINISTRATOR, USER, PUBLIC_USER, UNKNOWN] description: The type of participant. acceptanceStatus: type: string enum: [INVITED, ACCEPTED, REMOVED, UNKNOWN] description: The status of the participant accepting the shared record. ShortGUIDResult: type: object description: | The result of resolving or accepting a single share, as returned by `records/resolve` and `records/accept`. properties: shortGUID: $ref: '#/components/schemas/ShortGUID' containerIdentifier: type: string description: The container holding the shared record. databaseScope: type: string enum: [PUBLIC, PRIVATE, SHARED] description: The database scope holding the shared record. environment: type: string enum: [development, production] description: The container environment holding the shared record. zoneID: $ref: '#/components/schemas/ZoneID' rootRecordName: type: string description: The name of the root record that was shared. rootRecord: $ref: '#/components/schemas/RecordResponse' share: $ref: '#/components/schemas/RecordResponse' ownerIdentity: $ref: '#/components/schemas/UserIdentity' participantPermission: type: string enum: [NONE, READ_ONLY, READ_WRITE, UNKNOWN] description: The caller's read and write permissions on the share. participantStatus: type: string enum: [INVITED, ACCEPTED, REMOVED, UNKNOWN] description: The caller's acceptance status for the share. participantType: type: string enum: [OWNER, ADMINISTRATOR, USER, PUBLIC_USER, UNKNOWN] description: The caller's participant type for the share. webpageURL: type: string description: | The fallback webpage configured in CloudKit Dashboard, used to direct users somewhere when the operation fails. potentialMatchList: type: array description: | When the participant is not identifiable, the potential participants the user can choose from. items: type: object properties: participantId: type: string contactInformation: type: object properties: emailAddress: type: string phoneNumber: type: string ShortGUIDResultResponse: type: object description: | The response body for `records/resolve` and `records/accept`. properties: results: type: array items: $ref: '#/components/schemas/ShortGUIDResult' ContactsResponse: type: object properties: contacts: type: array items: type: object AssetUploadResponse: type: object properties: tokens: type: array items: type: object properties: url: type: string recordName: type: string fieldName: type: string AssetRereferenceResponse: type: object description: | Response body for `assets/rereference`: one reusable asset descriptor per requested asset field, wrapped under `assets`. Verified against the live service: the endpoint validates atomically — a bad entry (e.g. a missing source record) fails the *whole* request with a top-level HTTP 400, so there are no inline per-item failures here (unlike `ModifyResponse`/`LookupResponse`). properties: assets: type: array items: $ref: '#/components/schemas/AssetValue' TokenResponse: type: object description: | Response body for `tokens/create`. Per Apple's archived REST reference, the server returns the echoed environment, the minted APNs token, and a long-poll URL that browser/Service-Worker callers use to receive push notifications. Server-side callers typically only need `apnsToken`. required: - apnsEnvironment - apnsToken - webcourierURL properties: apnsEnvironment: type: string enum: [development, production] description: The APNs environment the token targets (echoes the request). apnsToken: type: string description: The CloudKit-minted APNs token to use as a push destination. webcourierURL: type: string format: uri description: | Long-poll endpoint URL that browser / Service-Worker clients use to receive push notifications. Not relevant for server callers, which receive pushes via APNs proper. OperationFailureServerErrorCode: type: string description: | The CloudKit server error code returned in a per-item failure entry (record or subscription) inline in a 200 modify/lookup response. Shared by `RecordOperationFailure` and `SubscriptionOperationFailure` via `OperationFailureCommon`. Distinct from `ErrorResponse`'s `serverErrorCode`, which carries a broader set of codes for top-level 4xx/5xx HTTP failures. enum: - ACCESS_DENIED - ATOMIC_ERROR - AUTHENTICATION_FAILED - AUTHENTICATION_REQUIRED - BAD_REQUEST - CONFLICT - EXISTS - INTERNAL_ERROR - NOT_FOUND - QUOTA_EXCEEDED - THROTTLED - TRY_AGAIN_LATER - VALIDATING_REFERENCE_ERROR - ZONE_NOT_FOUND OperationFailureCommon: type: object description: | Shared fields of a per-item failure entry returned inline in a 200 modify/lookup response. Composed into `RecordOperationFailure` and `SubscriptionOperationFailure` via `allOf`; each concrete failure type adds its own wire identifier (`recordName` / `subscriptionID`). required: - serverErrorCode properties: serverErrorCode: $ref: '#/components/schemas/OperationFailureServerErrorCode' reason: type: string description: A string indicating the reason for the error. retryAfter: type: integer description: Suggested seconds to wait before retrying. Absent if not retryable. uuid: type: string description: A unique identifier for this error. redirectURL: type: string description: Redirect URL for sign-in; present when serverErrorCode is AUTHENTICATION_REQUIRED. RecordOperationFailure: description: | Per-record error returned inline in the `records` array of a 200 modify/lookup response. Identifies the record that failed and why. Distinct from `ErrorResponse`, which is the body of a top-level 4xx/5xx HTTP failure. Note CloudKit does not echo `recordType` on a record error. allOf: - $ref: '#/components/schemas/OperationFailureCommon' - type: object required: - recordName properties: recordName: type: string description: The name of the record that the operation failed on. ErrorResponse: type: object description: | Error response object. For a full list of error codes and meanings, see: https://developer.apple.com/library/archive/documentation/DataManagement/Conceptual/CloudKitWebServicesReference/ErrorCodes.html#//apple_ref/doc/uid/TP40015240-CH4-SW1 Common error codes include: - AUTHENTICATION_FAILED: The request could not be authenticated. - ACCESS_DENIED: The user does not have permission to access the resource. - INVALID_ARGUMENTS: The request contained invalid parameters. - LIMIT_EXCEEDED: A request or resource limit was exceeded. - NOT_FOUND: The requested resource does not exist. - SERVICE_UNAVAILABLE: The service is temporarily unavailable. - ZONE_NOT_FOUND: The specified zone does not exist. - RECORD_NOT_FOUND: The specified record does not exist. - PARTIAL_FAILURE: Some, but not all, operations succeeded. See the documentation for a complete list and details. properties: uuid: type: string serverErrorCode: type: string enum: - ACCESS_DENIED - ATOMIC_ERROR - AUTHENTICATION_FAILED - AUTHENTICATION_REQUIRED - BAD_REQUEST - CONFLICT - EXISTS - INTERNAL_ERROR - NOT_FOUND - QUOTA_EXCEEDED - THROTTLED - TRY_AGAIN_LATER - VALIDATING_REFERENCE_ERROR - ZONE_NOT_FOUND description: | Server error code. See https://developer.apple.com/library/archive/documentation/DataManagement/Conceptual/CloudKitWebServicesReference/ErrorCodes.html#//apple_ref/doc/uid/TP40015240-CH4-SW1 for complete details. reason: type: string redirectURL: type: string responses: Failure: description: | Error response shared by all endpoints. The body schema is the same for every 4xx/5xx status code; the HTTP status code itself disambiguates which CloudKit failure occurred. See Apple's CloudKit Web Services Error Codes documentation for the full code → status mapping: - 400 BadRequest (BAD_REQUEST, ATOMIC_ERROR) - 401 Unauthorized (AUTHENTICATION_FAILED) - 403 Forbidden (ACCESS_DENIED) - 404 NotFound (NOT_FOUND, ZONE_NOT_FOUND) - 409 Conflict (CONFLICT, EXISTS) - 412 PreconditionFailed (VALIDATING_REFERENCE_ERROR) - 413 RequestEntityTooLarge (QUOTA_EXCEEDED) - 421 UnprocessableEntity (AUTHENTICATION_REQUIRED) - 429 TooManyRequests (THROTTLED) - 500 InternalServerError (INTERNAL_ERROR) - 503 ServiceUnavailable (TRY_AGAIN_LATER) content: application/json: schema: $ref: '#/components/schemas/ErrorResponse'