---
title: "Create APNs Token"
method: POST
path: "/device/{version}/{container}/{environment}/tokens/create"
tags: ["Tokens"]
---

# Create APNs Token

`POST /device/{version}/{container}/{environment}/tokens/create`

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")`).

## Path parameters

- `version` string, required — Protocol version
- `container` string, required — Container ID (begins with "iCloud.")
- `environment` 'development' | 'production', required — Container environment

## Request body

- object
  - `apnsEnvironment` 'development' | 'production', required
  - `clientId` string, required — 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.

## Response `200`

Token created successfully

- TokenResponse — 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`.
  - `apnsEnvironment` 'development' | 'production', required — The APNs environment the token targets (echoes the request).
  - `apnsToken` string, required — The CloudKit-minted APNs token to use as a push destination.
  - `webcourierURL` string, uri, required — 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.

## Other responses

- `400` — 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)
- `401` — 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)

## Changes

- **2026-05-31** `44029c7b63a3` — 1 info
  - endpoint added
- **2025-07-05** `a6d50d6e9dde` — 1 breaking
  - api path removed without deprecation

[Change history](https://skmtc.dev/brightdigit/apis/apple-cloudkit-web-services-api/changes/device/:version/:container/:environment/tokens/create/post.md)

---

[API](https://skmtc.dev/brightdigit/apis/apple-cloudkit-web-services-api.md) · [All operations](https://skmtc.dev/brightdigit/apis/apple-cloudkit-web-services-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/brightdigit/apple-cloudkit-web-services-api/revisions/db45a101c485/schema)
