> ## Documentation Index
> Fetch the complete documentation index at: https://docs.phosra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Register a device

> Register a device for on-device policy enforcement. Returns a one-time API key the iOS app stores in Keychain.

Register an Apple device against a child to drive on-device enforcement (Screen Time / MDM-style
controls). Once registered, the device pulls its compiled policy and reports activity back.

```bash theme={null}
curl -X POST https://phosra-api-sandbox-production.up.railway.app/api/v1/children/$CHILD_ID/devices \
  -H "Authorization: Bearer $PHOSRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Mia’s iPad","platform":"ios"}'
```


## OpenAPI

````yaml POST /children/{childID}/devices
openapi: 3.1.0
info:
  title: Phosra API
  description: Universal Parental Controls API - Define once, push everywhere
  version: 1.0.0
  contact:
    name: Phosra Developer Support
    url: https://docs.phosra.com
  license:
    name: Proprietary
    url: https://phosra.com/terms
servers:
  - url: https://phosra-api-sandbox-production.up.railway.app/api/v1
    description: >-
      Hosted sandbox — the one canonical, stable, partner-facing testing
      endpoint (seeded demo family + phosra_test_ keys). Default so the inline
      Try it never touches production. Same base the CLI uses.
  - url: https://prodapi.phosra.com/api/v1
    description: Production
  - url: http://localhost:8080/api/v1
    description: Local development
security:
  - BearerAuth: []
paths:
  /children/{childID}/devices:
    parameters:
      - name: childID
        in: path
        required: true
        schema:
          type: string
          format: uuid
    post:
      tags:
        - Apple Device Sync
      summary: Register an Apple device
      description: >-
        Register a device for on-device policy enforcement. Returns a one-time
        API key the iOS app stores in Keychain.
      operationId: registerAnAppleDevice
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterDeviceRequest'
      responses:
        '201':
          description: Device registered
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegisterDeviceResponse'
              example:
                device:
                  id: 5e0a9c37-1b64-4d82-96f3-2c8a7e0b4d19
                  child_id: ca02f5d1-fee8-4201-b5ca-fdc8be506e1e
                  family_id: fcdf4277-ba14-4732-8db5-0369b2c88d8b
                  platform_id: nextdns
                  device_name: Ada's iPhone
                  device_model: iPhone15,3
                  os_version: '18.5'
                  app_version: 2.4.0
                  apns_token: >-
                    8f7d3c1b2a90e64f5d8c7b6a1f0e9d3c2b1a0f9e8d7c6b5a4f3e2d1c0b9a8f7e6
                  capabilities:
                    - FamilyControls
                    - ManagedSettings
                    - DeviceActivity
                  enforcement_summary: {}
                  last_seen_at: '2026-07-05T22:04:18Z'
                  last_policy_version: 0
                  status: active
                  created_at: '2026-06-18T14:32:07Z'
                  updated_at: '2026-06-30T09:15:44Z'
                api_key: dvk_test_3a9f1c7e5b2d8046a1f3c9e7b5d2086
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: Child not found
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ServerError'
      x-codeSamples:
        - lang: JavaScript
          label: SDK (@phosra/sdk)
          source: >
            import { PhosraClient } from "@phosra/sdk";


            const phosra = new PhosraClient({
              baseUrl: "https://phosra-api-sandbox-production.up.railway.app/api/v1",
              accessToken: process.env.PHOSRA_API_KEY,
            });


            const result = await
            phosra.devices.register("a11ce0fa-0000-4000-8000-0000000000a1", {
              device_name: "Mia's iPhone",
              device_model: "iPhone15,2",
              os_version: "18.5",
              app_version: "1.4.0"
            });

            console.log(result);
        - lang: Shell
          label: cURL
          source: >
            curl -sS -X POST
            "https://phosra-api-sandbox-production.up.railway.app/api/v1/children/a11ce0fa-0000-4000-8000-0000000000a1/devices"
            \
              -H "Authorization: Bearer $PHOSRA_API_KEY" \
              -H "Content-Type: application/json" \
              -d '{
              "device_name": "Mia's iPhone",
              "device_model": "iPhone15,2",
              "os_version": "18.5",
              "app_version": "1.4.0"
            }'
        - lang: Python
          label: Python
          source: |
            import os, requests

            BASE = "https://phosra-api-sandbox-production.up.railway.app/api/v1"
            res = requests.post(
                f"{BASE}/children/a11ce0fa-0000-4000-8000-0000000000a1/devices",
                headers={"Authorization": f"Bearer {os.environ['PHOSRA_API_KEY']}"},
                json={
                    "device_name": "Mia's iPhone",
                    "device_model": "iPhone15,2",
                    "os_version": "18.5",
                    "app_version": "1.4.0"
                },
            )
            print(res.status_code, res.json())
        - lang: Go
          label: Go
          source: "package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc main() {\n\tbase := \"https://phosra-api-sandbox-production.up.railway.app/api/v1\"\n\tbody := bytes.NewBufferString(`{\n  \"device_name\": \"Mia's iPhone\",\n  \"device_model\": \"iPhone15,2\",\n  \"os_version\": \"18.5\",\n  \"app_version\": \"1.4.0\"\n}`)\n\treq, _ := http.NewRequest(\"POST\", base+\"/children/a11ce0fa-0000-4000-8000-0000000000a1/devices\", body)\n\treq.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"PHOSRA_API_KEY\"))\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\tout, _ := io.ReadAll(resp.Body)\n\tfmt.Println(resp.Status, string(out))\n}\n"
components:
  schemas:
    RegisterDeviceRequest:
      type: object
      required:
        - device_name
        - device_model
        - os_version
        - app_version
      properties:
        device_name:
          type: string
          description: User-assigned device name (e.g. "Ada's iPhone").
        device_model:
          type: string
          description: Hardware model identifier (e.g. `iPhone15,3`).
        os_version:
          type: string
          description: Operating-system version reported by the device (e.g. `18.5`).
        app_version:
          type: string
          description: Version of the Phosra app installed on the device.
        apns_token:
          type: string
          description: >-
            Apple Push Notification service device token; null until the device
            registers for push.
        capabilities:
          type: array
          items:
            type: string
          description: >-
            Apple frameworks the device supports (e.g. FamilyControls,
            ManagedSettings, DeviceActivity)
      additionalProperties: true
    RegisterDeviceResponse:
      type: object
      properties:
        device:
          $ref: '#/components/schemas/DeviceRegistration'
        api_key:
          type: string
          description: One-time device API key (store in Keychain)
      additionalProperties: true
    DeviceRegistration:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier for this resource.
        child_id:
          type: string
          format: uuid
          description: Identifier of the child this resource belongs to.
        family_id:
          type: string
          format: uuid
          description: Identifier of the family this resource belongs to.
        platform_id:
          type: string
          description: Identifier of the associated platform.
        device_name:
          type: string
          description: User-assigned device name (e.g. "Ada's iPhone").
        device_model:
          type: string
          description: Hardware model identifier (e.g. `iPhone15,3`).
        os_version:
          type: string
          description: Operating-system version reported by the device (e.g. `18.5`).
        app_version:
          type: string
          description: Version of the Phosra app installed on the device.
        apns_token:
          type:
            - string
            - 'null'
          description: >-
            Apple Push Notification service device token; null until the device
            registers for push.
        capabilities:
          type: array
          items:
            type: string
          description: >-
            Apple frameworks the device supports (e.g. FamilyControls,
            ManagedSettings, DeviceActivity)
        enforcement_summary:
          type: object
          description: >-
            Per-category enforcement results from the device's last
            enforcement_status report
          additionalProperties: true
        last_seen_at:
          type:
            - string
            - 'null'
          format: date-time
          description: RFC 3339 timestamp.
        last_policy_version:
          type: integer
          description: Policy version the device last successfully applied.
        status:
          type: string
          enum:
            - active
            - inactive
            - revoked
          description: Current lifecycle state of the resource.
        created_at:
          type: string
          format: date-time
          description: RFC 3339 timestamp of when the resource was created.
        updated_at:
          type: string
          format: date-time
          description: RFC 3339 timestamp of the resource's most recent update.
      additionalProperties: true
    Error:
      type: object
      properties:
        error:
          type: string
          description: >-
            Short, stable, machine-readable error class — matches the HTTP
            status text (e.g. `Not Found`).
        message:
          type: string
          description: >-
            Human-readable explanation of what went wrong and, where possible,
            how to fix it.
        code:
          type: integer
          description: Numeric HTTP status code, duplicated in the body for convenience.
      description: Standard error envelope returned for every 4xx and 5xx response.
      example:
        error: Not Found
        message: policy not found
        code: 404
      additionalProperties: true
  responses:
    BadRequest:
      description: >-
        The request was malformed — a required field is missing, a value failed
        validation, or an identifier is not a well-formed UUID.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Bad Request
            message: child_name is required
            code: 400
    Unauthorized:
      description: >-
        Authentication failed. Send a Bearer WorkOS JWT, or a
        `phosra_live_`/`phosra_test_` developer API key, in the `Authorization`
        header.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Unauthorized
            message: missing or invalid Authorization header
            code: 401
    Forbidden:
      description: >-
        Authenticated, but not permitted to act on this resource — for example,
        you are not a member of the target family.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Forbidden
            message: not a member of this family
            code: 403
    Conflict:
      description: >-
        The request conflicts with the current state of the resource — for
        example, a resource with the same natural key already exists.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Conflict
            message: resource already exists
            code: 409
    RateLimited:
      description: >-
        Too many requests. Back off and retry after the interval given in the
        `Retry-After` response header.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Too Many Requests
            message: rate limit exceeded
            code: 429
    ServerError:
      description: >-
        An unexpected error occurred inside Phosra. The request is safe to retry
        with exponential backoff; contact support if it persists.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Internal Server Error
            message: internal error
            code: 500
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````