WWDC Quick Look 💓 By SwiftGGTeam
Improve MDM assignment of Apps and Books

Improve MDM assignment of Apps and Books

Watch original video

Improve MDM distribution for apps and books

Highlight

The new Apps and Books Management API introduces real-time notifications and asynchronous processing, reducing 250,000 app allocations from a minimum of 25,000 requests to just 10 requests. Up to 25 apps can be allocated to 1,000 devices in a single request, with allocation status delivered in real time via push notifications.

Core Content

Managing application distribution to an enterprise or educational institution has always been a scaling challenge. A school with 10,000 students, one device per student, would need to distribute 25 core applications—a total of 250,000 distributions. The legacy API handled a single app allocation of up to 10 devices per request, which meant a minimum of 25,000 HTTP requests.

The new version of the Apps and Books Management API introduced at WWDC2021 solves this problem with two core improvements: real-time notifications eliminate the need for continuous polling, and asynchronous processing allows allocation operations to be performed in parallel on the server side. The same 250,000 allocations now require just 10 requests.

Detailed Content

Real-time notification type

The new version of the API supports four notification types, which need to be subscribed to separately by sToken in the client config (01:20):

Asset Management Notifications

Triggered when the allocation status changes, including associate (allocation), disassociate (deallocation), revoke (revocation) events (01:44):

{
  "notification": {
    "assignments": [
      {
        "adamId": "408709785",
        "pricingParam": "STDQ",
        "serialNumber": "C02Y402HLCM6"
      }
    ],
    "eventId": "87cbc650-16cc-4f9e-a833-e622f377a9f7",
    "result": "SUCCESS",
    "type": "ASSOCIATE"
  },
  "notificationType": "ASSET_MANAGEMENT",
  "uId": "2049025000431439"
}

After receiving the notification, you can send the installation command to the corresponding device without waiting for all batch operations to be completed.

Asset Count notification

Triggered when the app quantity changes as a result of a purchase, transfer, or refund (03:37):

{
  "notification": {
    "adamId": "408709785",
    "countDelta": 50,
    "pricingParam": "STDQ"
  },
  "notificationType": "ASSET_COUNT",
  "uId": "2049025000431439"
}

countDeltaA positive value indicates a purchase or transfer in, and a negative value indicates a refund or transfer out. MDM can directly update the local count with this increment without calling the sync endpoint.

User Management Notification

Triggered when registered user status changes, including create, update, and retire events (05:34):

{
  "notification": {
    "users": [
      {
        "clientUserId": "client-100",
        "idHash": "leSKk3IaE2vk2KLmv2k3/200D3=",
        "status": "Associated"
      }
    ],
    "eventId": "e0def1f8-9158-4343-9c52-8dd32da50b9b",
    "result": "SUCCESS",
    "type": "UPDATE"
  },
  "notificationType": "USER_MANAGEMENT"
}

User Associated Notifications

Triggered when the user accepts the invitation and associates the personal Apple ID with the registered account (08:33):

{
  "notification": {
    "associatedUsers": [
      {
        "clientUserId": "client-100",
        "idHash": "leSKk3IaE2vk2KLmv2k3/200D3=",
        "inviteCode": "f551b37da07146628e8dcbe0111f0364",
        "status": "Associated"
      }
    ]
  },
  "notificationType": "USER_ASSOCIATED"
}

Notification subscription configuration

Configure notification reception in client config (09:00):

  • notificationAuthToken: Shared secret, used by Apple in the notification’s Authorization header
  • notificationUrl: HTTPS endpoint to receive notifications

Returning HTTP 200 after receiving the notification indicates successful delivery. In case of non-200 response or timeout, Apple will retry a few times (best-effort). If you cannot receive notifications for a long time, you need to perform polling and synchronization for possible expired status.

Asynchronous processing

All operations in the legacy API were synchronous: you sent a request and waited for Apple to complete the allocation before returning a response (10:07). The new version is changed to asynchronous processing:

Legacy flow:
Request -> Apple performs the assignment synchronously -> return result (up to 10 devices x 1 app per request)

New flow:
Request -> Apple immediately returns eventId -> process asynchronously in the background -> push results through notifications
(up to 1,000 devices x 25 apps per request)

Advantages of asynchronous processing (10:25):

  • Forced parallelism on the server side to optimize processing speed
  • Orderly processing reduces intermittent failures and retries
  • Large-scale deployment is more reliable, making it easier for educational institutions to deploy during the back-to-school season

Actual comparison: 250,000 allocations

Take the scenario of 10,000 users × 25 applications as an example (11:08):

MetricsOld APINew API
Single request processing capacity1 application × 10 devices25 applications × 1,000 devices
Minimum number of requests25,00010
Response modeSynchronous waitingReturn eventId immediately
Result acquisitionObtain directly from the response bodyNotification push or query event status endpoint

Request format changes

The new API uses versioned URIs and correct HTTP methods (04:34). All requests carry sToken in the Authorization header in Bearer token format:

Authorization: Bearer <sToken>

Get asset status (GET request):

GET /v1/assets?adamId=408709785&pricingParam=STDQ

The response contains pagination information and asset count:

{
  "assets": [
    {
      "adamId": "408709785",
      "pricingParam": "STDQ",
      "assignedCount": 5000,
      "availableCount": 10000,
      "totalCount": 15000
    }
  ],
  "currentPageIndex": 0,
  "size": 1,
  "totalPages": 1
}

Assign assets (POST request):

// Request
{
  "assets": [
    { "adamId": "361309726", "pricingParam": "STDQ" }
  ],
  "serialNumbers": [
    "serial-1", "serial-2", ..., "serial-1000"
  ]
}

// Response
{
  "eventId": "92467a8e-8a50-4df9-9b30-f7ff4a99dea7",
  "tokenExpirationDate": "2021-07-06T14:12:10+0000"
}

Orderly processing

The new API ensures that operations within the same event are executed in the order of submission (13:49). For example, redistribution: first send a disassociate request to obtain eventId1, and then send an associate request to obtain eventId2. Apple ensures that all operations on eventId1 are completed before starting the operation on eventId2.

Version identification of Sync API

All sync API responses containversionId(07:28), changes when the underlying data is written. When traversing a large number of paginated responses, you can use versionId to detect whether the data of the previous page has changed.

Core Takeaways

  1. Migrate to the new version of API immediately: The old version of the API continues to be supported, but mixing old and new versions of the same sToken is not officially supported. The asynchronous processing and batch capabilities of the new API are the only way forward.

  2. Deployment notification receiving endpoint: ConfigurationnotificationUrlandnotificationAuthToken, subscribe to all four notification types. This is key to eliminating polling and enabling real-time state synchronization.

  3. Use batch requests to reduce the number of calls: Up to 25 applications × 1,000 devices in a single request. Organize and distribute batches rationally to keep the number of requests to a minimum.

  4. Use eventId to track asynchronous operations: Record the returned eventId after sending the allocation request, and then track the progress through notification or event status endpoint. Send the installation command to the device after receiving the success notification.

  5. Processing notification delivery failure: Apple’s notifications are best-effort delivery. If the service is unavailable and notifications are lost, perform targeted polling for potentially expired status instead of full synchronization.

Comments

GitHub Issues · utterances