Device Enrollment Program

In iOS 7 and later and macOS v10.9 and later, the Device Enrollment Program (DEP) helps to address the mass configuration needs of organizations purchasing and deploying devices in large quantities, without the need for factory customization or pre-configuration of devices prior to deployment.

A device enrolled in the Device Enrollment Program prompts the user to enroll in MDM during the initial device setup process. Additionally, devices enrolled in the program can be supervised over the air. Although Apple’s servers store information about the device’s participation in this program, the MDM profile and login challenge are served by the organization’s server.

The cloud service API provides profile management and mapping. With this API, you can obtain a list of devices, obtain information about those devices, and associate MDM enrollment profiles with those devices.

Device Management Workflow

A typical MDM device management workflow contains the following steps:

  1. Set up an account for your MDM server if you have not already done so.

  2. Use the Fetch Devices endpoint to obtain devices associated with the MDM server’s account.

  3. Assign a profile to the device. You can do this in one of the following ways:

    • Use the Define Profile endpoint to create a new MDM server profile and associate it with one or more devices.

    • Use the Assign Profile endpoint to associate an existing MDM server profile with one or more devices.

  4. Remove the profile from the device when appropriate by using the Remove Profile endpoint.

DEP Server Tokens

The MDM Device Enrollment Program (DEP) uses a server token to allow an MDM server to securely connect to the DEP web service.

Obtaining a Server Token

To obtain a DEP server token, the user must complete the steps outlined below. Your MDM server product can help by automating specific steps.

  1. Generate a public/private key pair in PEM format for the MDM server, and store the private key securely on the server.

  2. The user then must:

    1. Sign into the Device Enrollment Program web portal.

    2. Create a new virtual MDM server.

    3. Upload a PEM-encoded X.509 certificate containing the PEM public key that was generated in Step 1.

    4. Download the S/MIME encrypted token file generated by the program web portal.

  3. Decrypt the S/MIME encrypted server token.

  4. Upload the token file to the MDM server.

Using DEP Server Tokens

DEP server tokens can be deployed either automatically or manually.

Automatically

The MDM (physical) server must automatically decrypt this token file when it’s uploaded into the system, using the private key for the DEP web service.

Manually

Use the private key and provide an S/MIME encryption utility to manually decrypt the encrypted token file before it is uploaded to the MDM server. The MDM server then ingests a plain text token file for use with the DEP web service.

Server Token Example

Following is a S/MIME encrypted server token:

Content-Type: application/pkcs7-mime; name="smime.p7m"; smime-type=enveloped-
data
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7m"
Content-Description: S/MIME Encrypted Message
 
MIAGCSqGSIb3DQEHA6CAMIACAQAxggGeMIIBmgIBADCBgTB1MQswCQYDVQQGEwJVUzESMBAGA1UE
ChMJWmlwcG8gSW5jMSgwJgYDVQQDEx9Qcm9maWxlIE1hbmFnZXIgUy9NSU1FIElkZW50aXR5MSgw
JgYJKoZIhvcNAQkBFhlsb2NhbEB6aXBwb2luYzIuYXBwbGUuY29tAgiDS17MvQ95HDANBgkqhkiG
9w0BAQEFAASCAQC/ukglifm8tk/OjyKBWwPbm+uDNHPG+sXLRrwfTlHKRo1jnvYrqKx1bRrpV/GR
mN7WJPBZLOkFat+LoiEmrBUiUs3PnZ+U1FUAnHR66hnomKoX0JBgfuHBGYz9jeyiu1chQShgdOOe
bYQdaFPJ/P57r98yQ2ZmyqcYOWwE0lOcqa77bfRab/YmMsMx2ZE1wUwnFPM71Yq3+vLIGLBRyvAb
4pBxDlRtgGbxs+2gZwEe0MZ4tx/97RGnZbkJt/26v5P4njGiyCvq2hZUwbria7THhMEvmJRjpZNZ
x5BfTjU8a0EHwvvwnYb67LRnjoSMn/JgelRP70O9fhdZ5Y56xhs6MIAGCSqGSIb3DQEHATAdBglg
hkgBZQMEAQIEEF5d7PQ1O8lxOLjSwjNHwFaggASCAeC9GWg9EDLpyO2g6eoOmeIVYXbWXrRt4JRY
TqCB2dWDqc9BJqOYuX5lnULjvkJ8btlBfAMhUXUb/lFF5xNXGxLTtVHvyVK9FUyhikJFweRohWqM
/xtu+7/1rPT9Nmlssla9wcTAh8GsWbs9ZyM7Pnok+o1XOwRLgh1dGvW8EGxlaPWjcHolleFBStV6
lGKJUrUyzgyBvSWo/6Y/Ojb/kfzq/kzS6H7h4YZI69/Js604rpOL6FAeOwKaJLISfUUp/yNHMBr6
wj772MNnoIdVEQs14/Fk+XVDb4xghD1zzeDow+eseb+qEfY7FkgYi2jpdebk9X4BpJ1WGvy4WiA8
biyKpst6zJb0jdJ4TE0zyIcjuVeOXuV/cD1c7YrYQty1Sh3nBsjFwVOsHq33YjapcHf2wuhXW+hh
HNzpkyMKrNcsEK1HpJva2O6vBtxtYZIn5/4kGDeALUiXxVjtvio1gS37lry5YKEwhYJ+cKKe3exZ
xhLfD67AINahDm868kEuKuHIl8gku+gSKAWlUVGNrPNt/M2rM+y4+4cm23R2f3VXYuNncnFFbulF
7VQuGd3wwtKncIACU5rze4b366rRBG1PCvB7abuRcmw9UrgzkRlH8tbOhORZ0Dgimd5knujsbKMA
AAAAAAAAAAAA

Following is the decrypted server token in plain text:

Content-Type: text/plain;charset=UTF-8
Content-Transfer-Encoding: 7bit
 
{"consumer_key":"CK_9dcd8190dde27dfddd9272c657e011f7bec9761676b1b11e46a2f61d3c
b1e482ef22093c7d54b23252f3bdb4d19b4d49","consumer_secret":"CS_27c083df1ab7271e
129cb23325dabaf0de95d087","access_token":"AT_O365587095O8247e0b5288abcdee25642
311746d67b5858ea5cO1389734861908","access_secret":"AS_8c3313de9a3462014c6c96f3
9dd7c3d4342b8cea","access_token_expiry":"2015-01-14T21:27:41Z"}

Authentication and Authorization

To obtain OAuth access credentials for a server, download a server token file while the server is being created on the portal. The token file contains a JSON object similar to the one shown below:

{
  "consumer_key": "CK_00fadb3d36c6094cf479838455321b7c",
  "consumer_secret": "CS_5fb17e5676db0cf875211937e5166d0f662ea1f9",
  "access_token": "AT_O2109279022Oe03b641fd6f07d7face7894211d521fd8bef09c3O137392",
  "access_secret": "AS_837c228d968ff303837086a5a54be645314ef755"
  "access_token_expiry": "2013-09-09T02:24:28Z"
}

Each service request to the MDM enrollment service must include an X-ADM-Auth-Session header.

If the request does not have a valid X-ADM-Auth-Session header, or the auth token has expired, the server returns an HTTP 401 Unauthorized error.

HTTP/1.1 401 Unauthorized
Content-Type: text/plain;Charset=UTF8
Content-Length: 9
WWW-Authenticate: ADM-Auth-Token
Date: Thu, 31 May 2012 21:23:37 GMT
Connection: close
 
UNAUTHORIZED

Requesting a New Session Authorization Token

A new X-ADM-Auth-Session can be requested by using the https://mdmenrollment.apple.com/session endpoint. This endpoint supports the OAuth 1.0a protocol for accessing protected resources. When you sign up for the Device Enrollment Program, your server is assigned four pieces of information:

  • consumer_key

  • consumer_secret

  • access_token

  • access_secret

Your OAuth request must provide these pieces of information along with a timestamp (in seconds since January 1, 1970 00:00:00 GMT) and a cryptographically random nonce that must be unique for all requests made with a given timestamp. The server’s time should be synchronized using time.apple.com or another trusted NTP provider.

The request must be signed using HMAC-SHA1, as described in http://oauth.net/core/1.0a/#signing_process.

For example:

GET /session HTTP/1.1
Authorization: OAuth realm="ADM",
       oauth_consumer_key="CK_00fadb3d36c6094cf479838455321b7c",
       oauth_token="AT_O2109279022Oe03b641fd6f07d7face7894211d521fd8bef09c3O137392",
       oauth_signature_method="HMAC-SHA1",
       oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
       oauth_timestamp="137131200",
       oauth_nonce="4572616e48616d6d65724c61686176",
       oauth_version="1.0"

For more information about the OAuth specification, see http://oauth.net/core/1.0a/.

Response Payload

The token service validates the request and replies with a JSON payload containing a single key, auth_session_token, that contains the new X-ADM-Auth-Session token. For example:

HTTP/1.1 200 OK
Date: Thu, 28 Feb 2013 02:24:28 GMT
Content-Type: application/json;charset=UTF8
Content-Length: 47
Connection: close
 
{
    "auth_session_token" : "87a235815b8d6661ac73329f75815b8d6661ac73329f815"
}

After a period of time, this token expires, and the service returns a 401 error code. At this point, the MDM server must obtain a new session token from the https://mdmenrollment.apple.com/session endpoint.

Authentication Error Codes

An authentication error commonly results in either a 400, 401, or 403 error code.

An HTTP 400 Bad Request error indicates one of the following:

  • Unsupported oauth parameters

  • Unsupported signature method

  • Missing required authorization parameter

  • Duplicated OAuth protocol parameter

An HTTP 401 Unauthorized error indicates one of the following:

  • Invalid consumer key

  • Invalid or expired token

  • Invalid signature

  • Invalid or already-used nonce

An HTTP 403 Forbidden error indicates one of the following:

  • The MDM server does not have access to perform the specific request or the MDM server’s consumer key or token does not have authorization to perform the specific request. In this case, the request body contains ACCESS_DENIED.

  • The organization has not accepted latest Terms and Conditions of the program. In this case, the request body contains T_C_NOT_SIGNED.

For example, the following is the response when the MDM server is not authorized to perform a given request.

HTTP/1.1 403 Forbidden
Content-Type: text/plain;Charset=UTF8
Content-Length: 13
Date: Thu, 31 May 2012 21:23:57 GMT
Connection: close
 
ACCESS_DENIED

Web Services

This section lists the services that Apple’s servers provide to your MDM server. Except where otherwise specified, all requests must be sent with the following HTTP headers:

Header

Value

User-Agent

Your MDM server’s user agent string.

X-Server-Protocol-Version

1, 2, or 3.

X-ADM-Auth-Session

An authentication token value.

This header may be omitted when requesting an authentication token.

Content-Type

application/json;charset=UTF8

This header may be omitted for requests that do not include a request body.

For example:

GET /account HTTP/1.1
User-Agent: ProfileManager-1.0
X-Server-Protocol-Version:2
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815

The sections below describe the available commands.

Account Details

Each MDM server must be registered with Apple. This endpoint provides details about the server entity to identify it uniquely throughout your organization. Each server can be identified by either its system-generated UUID or by a user-provided name assigned by one of the organization’s users. Both the UUID and server name must be unique within your organization.

URL

https://mdmenrollment.apple.com/account

Query Type

GET

Request Body

This request does not require a request body.

For example, your MDM server might make the following request:

GET /account HTTP/1.1
User-Agent: ProfileManager-1.9
Content-Length: 0
X-Server-Protocol-Version:3
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Response Body

In response, the MDM enrollment service returns a JSON dictionary with the following keys:

Key

Value

server_name

An identifiable name for the MDM server.

server_uuid

A system-generated server identifier.

admin_id

Apple ID of the person who generated the current tokens that are in use.

facilitator_id

Legacy equivalent to the admin_id key. This key is deprecated and may not be returned in future responses.

org_name

The organization name.

org_email

The organization email address.

org_phone

The organization phone.

org_address

The organization address.

urls

The list of dictionaries (see below) containing URLs available in MDM service. This key is valid in X-Server-Protocol-Version 3 and later.

org_type

Possible values: edu or org. This key is available only in protocol version 3 and later.

org_version

Possible values: v1 or v2. v1 is for ADP organizations and v2 is for ASM organizations. Currently v2 is applicable only to educational organizations. This key is available only in protocol version 3 and later.

org_id

DEP customer ID. This key is available only in protocol version 3 and later.

org_id_hash

Returns the SHA hash of an org identifier. This helps MDMs match it with the organizationIdHash key in the VPPClientConfigSrv API. This key is available only in protocol version 3 and later.

Each url dictionary contains the following keys:

Key

Value

uri

URI for the API.

http_method

Possible values: GET, POST, PUT, DELETE.

limit

Optional: Dictionary for limit parameter (see below).

Each limit dictionary contains the following keys:

Key

Value

default

Default value of limit.

maximum

Maximum value of limit.

For example, the server might send a response that looks like this:

HTTP/1.1 200 OK
Date: Thu, 28 Feb 2013 02:24:28 GMT
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Content-Length: 640
X-Server-Protocol-Version: 3
Connection: close
{
     "server_name" : "IT Department Server",
     "server_uuid" : "677cab70-fe18-11e2-b778-0800200c9a66",
     "admin_id" : "facilitator1@example.com",
     "facilitator_id" : "facilitator1@example.com",
     "org_name" : "Sample Inc",
     "org_phone" : "111-222-3333",
     "org_email" : "orgadmin@example.com",
     "org_address": "12 Infinite Loop, Cupertino, California 95014",
     "urls" : [
       {"uri":"/account","http_method":["GET"]},
       {"uri":"/server/devices","http_method":["POST"],
         "limit":{"default":100,"maximum":1000}},
       {"uri":"/devices/sync","http_method":["POST"]},
         "limit":{"default":100,"maximum":1000}},
       {"uri":"/devices","http_method":["POST"]},
       {"uri":"/devices/disown","http_method":["POST"]},
       {"uri":"/profile","http_method":["POST"]},
       {"uri":"/profile/devices","http_method":["POST"]},
       {"uri":"/profile","http_method":["POST"]},
       {"uri":"/profile/devices","http_method":["GET"]},
       {"uri":"/profile/devices","http_method":["DELETE"]},
     ],
     "org_type":"edu",
     "org_version":"v2"
     "org_id":"8938930387878",
      "org_id_hash":"987559fe5f1ac383ed8ffffaa7699f80f178472f3d697104727d7c5314159d64"
}

Fetch Devices

This request fetches a list of all devices that are assigned to this MDM server at the time of the request. This service should be used for loading an initial list of devices into the MDM server’s data store. Once the list of devices is loaded, device sync requests should be used to synchronize the list with any further changes.

This request provides a limited number of entries per request, using cursors to provide position information across requests.

URL

https://mdmenrollment.apple.com/server/devices

Query Type

POST

Request Body

The request body should contain a JSON dictionary with the following keys:

Key

Value

cursor

Optional. A hex string that represents the starting position for a request. This is used for retrieving the list of devices that have been added or removed since a previous request. On the initial request, this should be omitted.

limit

Optional. The maximum number of entries to return. The default value is 100, and the maximum value is 1000.

For example, your MDM server might make the following request:

POST /server/devices HTTP/1.1
User-Agent:ProfileManager-1.9
X-Server-Protocol-Version:2
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
 
{
"limit": 100,
"cursor": "1ac73329f75815"
}
Response Body

In response, the MDM enrollment service returns a JSON dictionary with the following keys:

Key

Value

cursor

Indicates when this request was processed by the enrollment server. The MDM server can use this value in future requests if it wants to retrieve only records added or removed since this request.

devices

An array of dictionaries providing information about devices, sorted in chronological order of enrollment from oldest to most recent.

fetched_until

A timestamp indicating the progress of the device fetch request, in ISO 8601 format.

more_to_follow

A Boolean value that indicates whether the request’s limit and cursor values resulted in only a partial list of devices. If true, the MDM server should then make another request (starting from the newly returned cursor) to obtain additional records.

Each device dictionary contains the following keys:

Key

Value

serial_number

The device’s serial number (string).

model

The model name (string).

description

A description of the device (string).

color

The color of the device (string).

asset_tag

The device’s asset tag (string), if provided by Apple.

profile_status

The status of profile installation—either "empty", "assigned", "pushed", or "removed".

profile_uuid

The unique ID of the assigned profile.

profile_assign_time

A time stamp in ISO 8601 format indicating when a profile was assigned to the device. If a profile has not been assigned, this field may be absent.

profile_push_time

A time stamp in ISO 8601 format indicating when a profile was pushed to the device. If a profile has not been pushed, this field may be absent.

device_assigned_date

A time stamp in ISO 8601 format indicating when the device was enrolled in the Device Enrollment Program.

device_assigned_by

The email of the person who assigned the device.

os

The device’s operating system: iOS, OSX, or tvOS. This key is valid in X-Server-Protocol-Version 2 and later.

device_family

The device’s Apple product family: iPad, iPhone, iPod, Mac, or AppleTV. This key is valid in X-Server-Protocol-Version 2 and later.

For example, the server might send a response that looks like this:

HTTP/1.1 200 OK
Date: Thu, 9 May 2013 02:24:28 GMT
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Content-Length: 640
Connection: Keep-Alive
 
{
       "devices" : [
             {
                 "serial_number" : "C8TJ500QF1MN",
                 "model" : "IPAD",
                 "description" : "IPAD WI-FI 16GB",
                 "color" : "black",
                 "asset_tag" : "304214",
                 "profile_status" : "empty",
                 "device_assigned_date" : "2013-04-05T14:30:00Z",
                 "device_assigned_by" : "facilitator1@sampleinc.com",
                 "os" : "iOS",
                 "device_family" : "iPad"
             },
             {
                 "serial_number" : "C8TJ500QF1MN",
                 "model" : "IPAD",
                 "description" : "IPAD WI-FI 16GB",
                 "color" : "white",
                 "profile_status" : "assigned",
                 "profile_uuid" : "88fc4e378fea4021a94b2d7268fbf767",
                 "profile_assign_time" : "2013-05-01T00:00:00Z",
                 "device_assigned_date" : "2013-04-05T15:30:00Z",
                 "device_assigned_by" : "facilitator1@sampleinc.com",
                 "os" : "iOS",
                 "device_family" : "iPad"
             }
       ]
       "fetched_until" : "2013-05-09T02:24:28Z",
       "cursor" : "1ac73329f75815",
       "more_to_follow" : "false"
}
Request-Specific Errors

In addition to the standard errors listed in Common Error Codes, this request can return the following errors:

  • A 400 error with INVALID_CURSOR in the response body indicates that an invalid cursor value was provided.

  • A 400 error with EXHAUSTED_CURSOR in the response body indicates that the cursor had returned all devices in previous calls.

Sync Devices

The sync service depends on a cursor returned by the fetch device service. It returns a list of all modifications (additions or deletions) since the specified cursor. The cursor passed to this endpoint should not be older than 7 days.

This service may return the same device more than once. You must resolve duplicates by matching on the device serial number and the op_type and op_date fields.

URL

https://mdmenrollment.apple.com/devices/sync

Query Type

POST

Request Body

The request body should contain a JSON dictionary with the following keys:

Key

Value

cursor

A hex string returned by a previous request that represents the starting position for a request.

The request returns results that describe any changes or additions to devices that happened after this starting position.

limit

Optional. The maximum number of entries to return. The default value is 100, and the maximum value is 1000.

For example, your MDM server might make the following request:

POST /devices/sync HTTP/1.1
User-Agent:ProfileManager-1.9
X-Server-Protocol-Version:2
Content-Type: application/json;charset=UTF8
Content-Length: 50
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
 
{
    "cursor": "1ac73329f75815",
    "limit" : 200
}
Response Body

In response, the MDM enrollment service returns a JSON dictionary with the following keys:

Key

Value

cursor

Indicates when this request was processed by the server. The MDM server can use this value in future requests if it wants to retrieve only records added or removed since this request.

more_to_follow

Indicates that the request’s limit and cursor values resulted in only a partial list of devices. The MDM server should immediately make another request (starting from the newly returned cursor) to obtain additional records.

devices

An array of dictionaries providing information about devices, sorted in chronological order by the time stamp of the operation performed on the device.

fetched_until

A date stamp indicating the progress of the device fetch request, in ISO 8601 format.

Each device dictionary contains some of the following keys:

Key

Value

serial_number

The device’s serial number (string).

model

The model name (string).

description

A description of the device (string).

color

The color of the device (string).

asset_tag

The device’s asset tag (string).

profile_status

The status of profile installation—either "empty", "assigned", "pushed", or "removed".

profile_uuid

The unique ID of the assigned profile.

profile_assign_time

A time stamp in ISO 8601 format indicating when a profile was assigned to the device.

profile_push_time

A time stamp in ISO 8601 format indicating when a profile was pushed to the device.

op_type

Indicates whether the device was added (assigned to the MDM server), modified, or deleted. Contains one of the following strings: added, modified, or deleted.

op_date

A time stamp in ISO 8601 format indicating when the device was added, updated, or deleted. If the value of op_type is added, this is the same as device_assigned_date.

device_assigned_by

The email of the person who assigned the device.

device_assigned_date

A time stamp in ISO 8601 format indicating when the device was assigned to the MDM server.

os

The device’s operating system: iOS, OSX, or tvOS. This key is valid in X-Server-Protocol-Version 2 and later.

device_family

The device’s Apple product family: iPad, iPhone, iPod, Mac, or AppleTV. This key is valid in X-Server-Protocol-Version 2 and later.

For example, the server might send a response that looks like this:

HTTP/1.1 200 OK
Date: Thu, 9 May 2013 03:24:28 GMT
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Content-Length: 640
Connection: Keep-Alive
 
{
        "devices" : [
                {
                    "serial_number" : "C8TJ500QF1MN",
                    "model" : "IPAD",
                    "color" :    "black",
                    "description" : "IPAD WI-FI 16GB",
                    "asset_tag" : "304214",
                    "profile_status" : "empty",
                    "op_type" : "added",
                    "op_date" : "2013-05-09T14:30:00Z",
                    "device_assigned_by" : "facilitator1@sampleinc.com",
                    "device_assigned_date" : "2013-05-09T14:30:00Z",
                    "os" : "iOS",
                    "device_family" : "iPad"
                },
                {
                    "serial_number" : "C8TJ500QF1MN",
                    "model" : "IPAD",
                    "color" :    "white",
                    "description" : "IPAD WI-FI 16GB",
                    "op_type" : "deleted",
                    "op_date" : "2013-05-09T14:30:00Z",
                    "device_assigned_by" : "facilitator1@sampleinc.com",
                    "device_assigned_date" : "2013-05-09T14:30:00Z",
                 "os" : "iOS",
                 "device_family" : "iPad"
                }
            ],
        "more_to_follow" : false,
        "cursor" : "2ac73329f75815"
}
Request-Specific Errors

In addition to the standard errors listed in Common Error Codes, this request can return the following errors:

  • A 400 error with CURSOR_REQUIRED in the response body indicates that no cursor value was provided.

  • A 400 error with INVALID_CURSOR in the response body indicates that an invalid cursor value was provided.

  • A 400 error with EXPIRED_CURSOR in the response body indicates that the provided cursor is older than 7 days.

Device Details

Returns information about an array of devices.

URL

https://mdmenrollment.apple.com/devices

Query Type

POST

Request Body

The request body should contain a JSON dictionary with the following keys:

Key

Value

devices

An array of strings containing device serial numbers.

For example, your MDM server might make the following request:

POST /devices HTTP/1.1
User-Agent:ProfileManager-1.0
X-Server-Protocol-Version:2
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
 
{
    "devices":["C8TJ500QF1MN", "B7CJ500QF1MA"]
}
Response Body

In response, the MDM enrollment service returns a JSON dictionary of dictionaries. The outer dictionary keys are the serial numbers from the original request. Each value is a dictionary with the following keys:

Key

Value

response_status

A string indicating whether a particular device’s data could be retrieved—either SUCCESS or NOT_FOUND.

os

The device’s operating system: iOS, OSX, or tvOS. This key is valid in X-Server-Protocol-Version 2 and later.

device_family

The device’s Apple product family: iPad, iPhone, iPod, Mac, or AppleTV. This key is valid in X-Server-Protocol-Version 2 and later.

serial_number

The device’s serial number (string).

model

The model name (string).

description

A description of the device (string).

color

The color of the device (string).

asset_tag

The device’s asset tag (string).

device_assigned_by

The email of the person who assigned the device.

device_assigned_date

A time stamp in ISO 8601 format indicating when the device was assigned to the MDM server.

profile_status

The status of profile installation: either empty, assigned, pushed, or removed. If empty, no other profile fields are present.

profile_uuid

The unique ID of the assigned profile.

profile_assign_time

A time stamp in ISO 8601 format indicating when a profile was assigned to the device.

profile_push_time

A time stamp in ISO 8601 format indicating when a profile was pushed to the device.

For example, the server might send a response that looks like this:

HTTP/1.1 200 OK
Date: Thu, 9 May 2013 03:24:28 GMT
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Content-Length: 259
Connection: Keep-Alive
{
  "devices":
  {
 
      "C8TJ500QF1MN" :
      {
        "response_status" : "SUCCESS",
        "os" : "iOS",
        "device_family" : "iPad",
        "model" : "IPAD",
        "description" : "IPAD WI-FI 16GB",
        "color": "BLACK",
        "asset_tag" : "304214",
        "device_assigned_by" : "facilitator1@sampleinc.com",
        "device_assigned_date" : "2013-01-01T14:30:00Z",
        "profile_uuid" : "88fc4e378fea4021a94b2d7268fbf767",
        "profile_assign_time" : "2013-01-01T00:00:00Z",
        "profile_push_time" : "2013-02-01T00:00:00Z"
      },
      "B7CJ500QF1MA" : {
        "response_status" : "NOT_FOUND"
      }
   }
}
Request-Specific Errors

In addition to the standard errors listed in Common Error Codes, this request can return the following errors:

  • A 200 error with NOT_FOUND in the response body indicates that the specified device is not accessible by the MDM server.

  • A 400 error with DEVICE_ID_REQUIRED in the response body indicates that the request did not contain any devices.

Disown Devices

Tells Apple’s servers that your organization no longer owns one or more devices. This request is deprecated and may not be supported in the future.

 URL

https://mdmenrollment.apple.com/devices/disown

Query Type

POST

Request Body

The request body should contain a JSON dictionary with the following keys:

Key

Value

devices

Array of strings containing device serial numbers.

For example, your MDM server might make the following request:

POST /devices/disown HTTP/1.1
User-Agent:ProfileManager-1.0
X-Server-Protocol-Version:2
Content-Type: application/json;charset=UTF8
Content-Length: 30
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
 
{
    "devices":["C8TJ500QF1MN", "B7CJ500QF1MA"]
}
Response Body

In response, the MDM enrollment service returns a JSON dictionary with the following keys:

Key

Value

devices

A dictionary of devices. Each key in this dictionary is the serial number of a device in the original request. Each value is one of the following values:

  • SUCCESS: Device was successfully disowned.

  • NOT_ACCESSIBLE: A device with the specified ID was not accessible by this MDM server.

  • FAILED: Disowning the device failed for an unexpected reason. If three retries fail, the user should contact Apple support.

If no devices were provided in the original request, this dictionary may be absent.

For example, the server might send a response that looks like this:

HTTP/1.1 200 OK
Date: Thu, 9 May 2013 03:24:28 GMT
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Content-Length: 160
Connection: Keep-Alive
 
{
    "devices": {
        "C8TJ500QF1MN":"SUCCESS",
        "B7CJ500QF1MA":"NOT_ACCESSIBLE"
    }
}
Request-Specific Errors

In addition to the standard errors listed in Common Error Codes, this request can return the following errors:

  • A 400 error code with DEVICE_ID_REQUIRED in the response body indicates that no device IDs (serial numbers) were provided.

Activation Lock

Find My iPhone Activation Lock is a feature of iCloud that makes it harder for anyone to use or resell a lost or stolen iOS device that has been enrolled under DEP.

The Activation Lock request is available in X-Server-Protocol-Version 2 and later to organizations that have enrolled through the Apple School Manager portal.

Request

To lock a device, POST an HTTP request in application/json format to the following URL: https://mdmenrollment.apple.com/device/activationlock. The request header must follow this format:

POST /device/activationlock HTTP/1.1
User-Agent:<client-software-information>
X-Server-Protocol-Version: <Integer, 2 or higher>
X-ADM-Auth-Session:<AUTH-TOKEN>
Content-Type: application/json;charset=UTF8
Content-Length: <Content_Length>
...

Immediately following the request header, send these content keys and values in application/json format:

Key

Type

Content

device

String

Serial number of the device (required).

escrow_key

String

Escrow key (optional). If the escrow key is not provided, the device will be locked against the person who created the MDM server in the portal. For information about creating an escrow key see Escrow Keys and Bypass Codes.

lost_message

String

Lost message to be displayed on the device (optional).

A typical request might look like this:

POST /device/activationlock HTTP/1.1
User-Agent:ProfileManager-1.0
X-Server-Protocol-Version:2
Content-Type: application/json;charset=UTF8
Content-Length: 122
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
{
   "device": "C8TJ500QF1MN",
   "escrow_key": "30a3449822ae82b94f1839ee0248a9e2350247d4
                  b325071e6deb84285a6bfb34",
   "lost_message": "Please phone 1-800-555-1212"
}
Response

The Apple server responds to the Activation Lock request with the following two keys:

Key

Type

Content

serial_number

String

Serial number of the device.

response_status

String

SUCCESS or one of the failure responses listed below.

Activation lock failure responses include the following:

Response

Reason

NOT_ACCESSIBLE

A device with this serial number is not accessible by this user.

ORG_NOT_SUPPORTED

A device with this serial number is not supported because it is not present in the new program.

DEVICE_NOT_SUPPORTED

Device type is not supported like Mac.

DEVICE_ALREADY_LOCKED

Device is already locked by someone.

FAILED

Activation lock of the device failed for unexpected reason. If retry fails, the client should contact Apple support.

A successful activation lock response typically looks like this:

HTTP/1.1 200 OK
Date: Thu, 9 May 2013 03:24:28 GMT
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Content-Length: 160
Connection: Keep-Alive
{
     "serial_number" : "B7CJ500QF1MA",
     "response_status" : "SUCCESS"
}

Server failures during activation lock attempts typically look like one of the following two examples:

HTTP/1.1 500 Internal Server Error
Content-Type: text/plain;charset=UTF8
Content-Length: 0
Date: Thu, 31 May 2012 21:23:57 GMT
Connection: close
 
HTTP/1.1 503 Service Unavailable
Content-Type: text/plain;charset=UTF8
Retry-After: 120
Content-Length: 0
Date: Thu, 31 May 2012 21:23:57 GMT
Connection: close

A client failure during an activation lock attempt may look like this:

HTTP/1.1 4xx <Error Reason>
Content-Type: text/plain;Charset=UTF8
Content-Length: 10
Date: Thu, 31 May 2012 21:23:57 GMT
Connection: close
 
<ERROR_CODE>

The combination of the ERROR_CODE in the response body shown above and the HTTP error typically indicates one of the following reasons for a client failure during an activation lock attempt:

  • UNAUTHORIZED + HTTP 401: The auth token has expired. The client should retry with a new auth token.

  • FORBIDDEN + HTTP 403: The auth token is invalid.

  • MALFORMED_REQUEST_BODY + HTTP 400: The request body is malformed.

Activation Lock Bypass

iOS 7.1 adds support for Activation Lock Bypass. This allows organizations to remove the Activation Lock from supervised devices prior to device activation without knowing the user’s personal Apple ID and password.

When an iOS device is configured as supervised it can generate a device-specific Activation Lock bypass code. A cryptographically-secure hash of the bypass code is stored by Apple’s activation server. This hash allows the activation server to verify that the correct bypass code has been provided to the device. For further information see Escrow Keys and Bypass Codes.

When the device creates a bypass code and hash, they’re stored in the device’s keychain and marked as available after first unlock and non-exportable.

To retrieve the bypass code, the MDM server uses the ActivationLockBypassCode query:

Key

Type

Content

RequestType

String

ActivationLockBypassCode.

If a bypass code has never been created on the device, a new one is created when this query is received. Either way the bypass code is returned, if possible:

Key

Type

Content

ActivationLockBypassCode.

String

The activation lock bypass code, if it’s available.

Once retrieved and stored by the MDM server, the bypass code can be removed from the device using the ClearActivationLockBypassCode command:

Key

Type

Content

ClearActivationLockBypassCode

String

Supervised only. Clears the activation lock bypass code from the device.

If the command is successful, an Acknowledged status is returned. If not removed, the bypass code is automatically deleted from the device after 15 days.

Once a device is erased, the bypass code can be manually entered when prompted by the Setup Assistant, leaving the username field empty. However, it’s recommended that an MDM server should clear the activation lock, using the web service described below, prior to erasing a device.

Authentication

The MDM server must provide its APNS certificate when establishing the SSL connection with the web service.

Request

To remove an activation lock, provide the device’s bypass code to the web service. The request should be a standard HTTPS POST on port 443 to https://deviceservices-external.apple.com/ deviceservicesworkers/escrowKeyUnlock. The request must also have the contentType header set to application/x-www-form-urlencoded.

The following arguments must be provided as part of the URL request string:

Argument

Description

serial

The device’s serial number (required).

imei

Device IMEI (omitted for non-carrier devices).

meid

Device MEID (omitted for non-carrier devices).

productType

Example: iPod4,1 (required).

The following arguments must go into the message body:

Argument

Description

orgName

Client-supplied value for auditing purposes: a string such as the name of the organization.

guid

Client-supplied value for auditing purposes: a string that identifies the user requesting the removal (email, LDAP ID, name, etc.).

escrowKey

The device’s bypass code. For further information see Escrow Keys and Bypass Codes.

Arguments provided in the message body should be formatted as parameters in a form submission. For example:

escrowKey=abcdefg&orgName=Acme+Inc&guid=123456

The arguments string should comprise the entire message body.

HTTP Response Codes

The services can return any of the HTTP status codes, and the client is expected to handle the range of status codes. The more common ones include:

Code

Description

200

Success.

400

Failure: bad request; likely cause is a malformed request query or body.

404

Failure: device is not found, or escrowKey is invalid.

500

Unexpected server error; try again later.

Response Body Format

The response body may contain diagnostic information useful when reporting issues to Apple. Do not rely on specific codes, because they may change.

Escrow Keys and Bypass Codes

Your MDM server implementation should store two bypass codes:

  • The device-generated bypass code retrieved using the ActivationLockBypassCode device query. The server should retain this code until it receives a different, non-empty code from the device.

  • The bypass code the server creates when initiating an activation lock through MDM.

The server should try to unlock the device with the bypass code most likely to be active, then try the other code if the first one fails. It is impossible for the server to be certain which code is active at a given time (or even to determine if the device is locked at all) because the device can always be erased and its activation lock removed manually by entering the correct Apple ID or password. The device’s IsActivationLockEnabled value is not an accurate reflection of its true activation lock state because the device can report either a false positive or a false negative.

Following is a sample of code that generates both an escrow key and a bypass code:

#define MCBYPASS_CODE_LENGTH 31 // Excluding terminating null
#define MCBYPASS_CODE_BUFFER_LENGTH 32 // Including terminating null
#define MCBYPASS_RAW_BYTES_LENGTH 16
#define MCBYPASS_HASH_LENGTH CC_SHA256_DIGEST_LENGTH
 
- (NSString*) _createNewActivationLockBypassCodeOutHash:(NSString**)outHash
{
#define RANDOM_BYTES_LENGTH 16
#define SALT_LENGTH 4
    // Encode raw bytes
    static const char kSymbols[] = "0123456789ACDEFGHJKLMNPQRTUVWXYZ";
                                //  00000000000000001111111111111111
                                //  0123456789abcdef0123456789abcdef
 
    // Insert dashes after outputting characters at these positions
    static const int kDashPositions[] = { 5, 10, 14, 18, 22 };
 
    char    rawBytes[MCBYPASS_RAW_BYTES_LENGTH];
    char    code[MCBYPASS_CODE_BUFFER_LENGTH];
    uint8_t hash[MCBYPASS_HASH_LENGTH];
    uint8_t salt[SALT_LENGTH] = {0, 0, 0, 0};
 
    arc4random_buf(rawBytes, RANDOM_BYTES_LENGTH);
    CCKeyDerivationPBKDF(kCCPBKDF2, rawBytes, RANDOM_BYTES_LENGTH, salt, SALT_LENGTH,
        kCCPRFHmacAlgSHA256, 50000, hash, CC_SHA256_DIGEST_LENGTH);
 
    if (outHash) *outHash = [NSData dataWithBytes:hash
        length:MCBYPASS_HASH_LENGTH].hexString;
 
    int         outputCharacterCount = 0;
    const int*  nextDashPosition     = kDashPositions;
    char*       outputCursor         = code;
    uint8_t*    inputCursor          = (uint8_t*)rawBytes;
 
    // Generate output one symbol at a time
#define INPUT_BITS      128
#define BITS_PER_BYTE   8
#define BITS_PER_SYMBOL 5
 
    int bitsProcessed     = 0;
    int bitOffsetIntoByte = 0;
    while (bitsProcessed <= (INPUT_BITS - BITS_PER_SYMBOL)) {
        int bitsThisByte = (bitOffsetIntoByte < BITS_PER_BYTE - BITS_PER_SYMBOL
            ? BITS_PER_SYMBOL : BITS_PER_BYTE - bitOffsetIntoByte);
        int bitsNextByte = (bitsThisByte < BITS_PER_SYMBOL ? BITS_PER_SYMBOL
            - bitsThisByte : 0);
 
        uint8_t value = (((*inputCursor << bitOffsetIntoByte) & 0xff)
        >> (BITS_PER_BYTE - bitsThisByte));
 
        bitOffsetIntoByte += BITS_PER_SYMBOL;
        if (bitOffsetIntoByte >= BITS_PER_BYTE) {
            bitOffsetIntoByte -= BITS_PER_BYTE;
            inputCursor++;
        }
 
        if (bitsNextByte) {
            value <<= bitsNextByte;
            value |= (*inputCursor >> (BITS_PER_BYTE - bitsNextByte));
        }
 
       *outputCursor++ = kSymbols[value];
        if (++outputCharacterCount == *nextDashPosition) {
            ++nextDashPosition;
            *outputCursor++ = '-';
        }
 
        bitsProcessed += BITS_PER_SYMBOL;
    } // while
 
    // Process remaining bits
    int bitsRemaining = INPUT_BITS - bitsProcessed;
    if (bitsRemaining) {
        uint8_t value = (((*inputCursor << bitOffsetIntoByte) & 0xff)
            >> (BITS_PER_BYTE - bitsRemaining));
       *outputCursor++ = kSymbols[value];
    }
    *outputCursor = '\0';
    return [NSString stringWithUTF8String:code];
} // -_createNewActivationLockBypassCodeOutHash:
 

Define Profile

Tells Apple’s servers about a profile that can then be assigned to specific devices. This command provides information about the MDM server that is assigned to manage one or more devices, information about the host that the managed devices can pair with, and various attributes that control the MDM association behavior of the device.

 URL

https://mdmenrollment.apple.com/profile

Query Type

POST

Request Body

The request body should contain a JSON dictionary with the following keys:

Key

Value

profile_name

String. A human-readable name for the profile.

url

String. The URL of the MDM server.

allow_pairing

Optional. Boolean. Default is true.

is_supervised

Optional. Boolean. If true, the device must be supervised. Defaults to false.

is_multi_user

Optional. Boolean. If true, tells the device to configure for Shared iPad. Default is false. This key is valid in X-Server-Protocol-Version 2 and later.

Devices that do not meet the Shared iPad minimum requirements do not honor this command. With iOS devices, com.apple.mdm.per-user-connections must be added to the MDM enrollment profile’s ServerCapabilities. See iOS Support for Per-User Connections.

is_mandatory

Optional. Boolean. If true, the user may not skip applying the profile returned by the MDM server. Default is false.

await_device_configured

Optional. Boolean. If true, the device does not continue in Setup Assistant until the MDM server sends a command stating that the device is configured (see DeviceConfigured). Default is false. Ignored on iOS devices if is_supervised is false. This key is valid in X-Server-Protocol-Version 2 and later.

is_mdm_removable

If false, the MDM payload delivered by the configuration URL cannot be removed by the user via the user interface on the device; that is, the MDM payload is locked onto the device. This key can be set to false only if is_supervised is set to true. Defaults to true.

support_phone_number

Optional. String. A support phone number for the organization.

auto_advance_setup

Optional. Boolean. If set to true, the device will tell tvOS Setup Assistant to automatically advance though its screens. Default is false. This key is valid in X-Server-Protocol-Version 2 and later.

support_email_address

Optional. String. A support email address for the organization. This key is valid in X-Server-Protocol-Version 2 and later.

org_magic

A string that uniquely identifies various services that are managed by a single organization.

anchor_certs

Optional. Array of strings. Each string should contain a DER-encoded certificate converted to Base64 encoding. If provided, these certificates are used as trusted anchor certificates when evaluating the trust of the connection to the MDM server URL. Otherwise, the built-in root certificates are used.

supervising_host_certs

Optional. Array of strings. Each string contains a DER-encoded certificate converted to Base64 encoding. If provided, the device will continue to pair with a host possessing one of these certificates even when allow_pairing is set to false.

skip_setup_items

Optional. Array of strings. A list of setup panes to skip. The array may contain one or more of the following strings:

  • AppleID: Disables signing in to Apple ID and iCloud.

  • Biometric: Skips Touch ID setup.

  • Diagnostics: Disables automatically sending diagnostic information.

  • DisplayTone: Skips DisplayTone setup.

  • Location: Disables Location Services.

  • Passcode: Hides and disables the passcode pane.

  • Payment: Skips Apple Pay setup.

  • Restore: Disables restoring from backup.

  • Siri: Disables Siri.

  • TOS: Skips Terms and Conditions.

  • Zoom: Skips zoom setup.

  • Android: If the Restore pane is not skipped, removes Move from Android option from it.

  • HomeButtonSensitivity: Skips the Home Button screen in iOS.

  • Keyboard: Skips the keyboard selection screen in iOS.

  • OnBoarding: Skips on-boarding informational screens for user education (“Cover Sheet, Multitasking & Control Center”, for example) in iOS.

  • WatchMigraton: Skips the screen for watch migration in iOS.

  • FileVault: Disables FileVault Setup Assistant screen in macOS.

  • iCloudDiagnostics: Skips iCloud Analytics screen in macOS.

  • Registration: Disables registration screen in macOS.

  • ScreenSaver: Skips the tvOS screen about using aerial screensavers in ATV.

  • TapToSetup: Skips the Tap To Set Up option in ATV about using an iOS device to set up your ATV (instead of entering all your account information and setting choices separately).

  • TVHomeScreenSync: Skips TV home screen layout sync screen in tvOS.

  • TVProviderSignIn: Skips the TV provider sign in screen in tvOS.

department

Optional. String. The user-defined department or location name.

devices

Array of strings containing device serial numbers. (May be empty.)

For example, your MDM server might make the following request:

POST /profile HTTP/1.1
User-Agent:ProfileManager-1.0
X-Server-Protocol-Version:2
Content-Type: application/json;charset=UTF8
Content-Length: 350
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
 
{
   "profile_name": "Test Profile",
   "url":"https://mdm.acmeinc.com/getconfig",
   "is_supervised":false,
   "allow_pairing":true,
   "is_mandatory":false,
   "await_device_configured":false,
   "is_multi_user":false,
   "is_mdm_removable":false,
   "department": "IT Department",
   "org_magic": "913FABBB-0032-4E13-9966-D6BBAC900331",
   "support_phone_number": "1-555-555-5555",
   "anchor_certs":[
      "MIICkDCCAfmgAwIBAgIJAOAeuvyohALaMA0GCSqGSIb3DQEBBQUAMGExCzAJBgNVBAYT..."
   ],
   "supervising_host_certs:[
        "AlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJQ3VwZXJ0aW5vMRowGAYDVQQKDBFB…"
    ],
   "skip_setup_items":[
      "Location",
      "Restore",
      "Android",
      "AppleID",
      "TOS",
      "Siri",
      "Diagnostics",
      "HomeButtonSensitivity",
      "Biometric",
      "Payment",
      "Zoom",
      "DisplayTone",
      "FileVault",
      "TapToSetup",
      "ScreenSaver"
   ],
    "devices":["C8TJ500QF1MN", "B7CJ500QF1MA"]
}
Response Body

In response, the MDM enrollment service returns a JSON dictionary with the following keys:

Key

Value

profile_uuid

The profile’s UUID (hex string).

devices

A dictionary of devices. Each key in this dictionary is the serial number of a device in the original request. Each value is one of the following strings:

  • SUCCESS: The profile was mapped to the device.

  • NOT_ACCESSIBLE: A device with the specified serial number was not accessible by this server.

  • FAILED: Assigning the profile failed for an unexpected reason. If three retries fail, the user should contact Apple support.

For example, the server might send a response that looks like this:

HTTP/1.1 200 OK
Date: Thu, 9 May 2013 03:24:28 GMT
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Content-Length: 160
Connection: Keep-Alive
 
{
    "profile_uuid": "88fc4e378fea4021a94b2d7268fbf767",
    "devices": {
          "C8TJ500QF1MN":"SUCCESS",
          "B7CJ500QF1MA":"NOT_ACCESSIBLE"
    }
}
Request-Specific Errors

In addition to the standard errors listed in Common Error Codes, this request can return the following errors:

  • A 400 error code with CONFIG_URL_REQUIRED in the response body indicates that the MDM server URL is missing in the profile.

  • A 400 error code with CONFIG_NAME_REQUIRED in the response body indicates that the configuration name is missing in the profile.

  • A 400 error code with FLAGS_INVALID in the response body indicates that flags have been set incorrectly. Flag is_mdm_removable can be set to false only if flag is_supervised is set to true.

  • A 400 error code with CONFIG_URL_INVALID in the response body indicates that the URL field in the uploaded profile is either empty or has exceeded the maximum allowed length (2000 URL encoded characters). The syntax of the URL is defined by RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax, amended by RFC 2732: Format for Literal IPv6 Addresses in URLs.

  • A 400 error code with CONFIG_NAME_INVALID in the response body indicates that the profile_name field in the uploaded profile is either empty or has exceeded the maximum allowed length (125 UTF-8 characters).

  • A 400 error code with DEPARTMENT_INVALID in the response body indicates that the department field in the uploaded profile is either empty or has exceeded the maximum allowed length (125 UTF-8 characters).

  • A 400 error code with SUPPORT_PHONE_INVALID in the response body indicates that the support_phone_number field in the uploaded profile is either empty or has exceeded the maximum allowed length (50 UTF-8 characters).

  • A 400 error code with SUPPORT_EMAIL_INVALID in the response body indicates that the support_email_address field in the uploaded profile is either empty or has exceeded the maximum allowed length (250 UTF-8 characters).

  • A 400 error code with MAGIC_INVALID in the response body indicates that the magic field in the uploaded profile is either empty or has exceeded the maximum allowed length (256 UTF-8 characters).

Assign Profile

Tells Apple’s severs that the specified devices should use a particular profile defined by the Define Profile command.

URL

https://mdmenrollment.apple.com/profile/devices

Query Type

PUT

Request Body

The request body should contain a JSON dictionary with the following keys:

Key

Value

profile_uuid

The UUID (string) for the profile that you want to assign to the specified devices. This UUID was returned by a previous Define Profile request.

devices

Array of strings containing device serial numbers. An empty array is considered a no-op.

For example, your MDM server might make the following request:

PUT /profile/devices HTTP/1.1
User-Agent:ProfileManager-1.0
X-Server-Protocol-Version:2
Content-Type: application/json;charset=UTF8
Content-Length: 38
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
 
{
   "profile_uuid": "88fc4e378fea4021a94b2d7268fbf767",
    "devices":["C8TJ500QF1MN", "B7CJ500QF1MA"]
}
Response Body

In response, the MDM enrollment service returns a JSON dictionary with the following keys:

Key

Value

profile_uuid

The profile’s UUID (string).

devices

A dictionary of devices. Each key in this dictionary is the serial number of a device in the original request. Each value is a string with one of the following values:

  • SUCCESS: Profile was mapped to the device.

  • NOT_ACCESSIBLE: A device with the specified ID was not accessible by this MDM server.

  • FAILED: Assigning the profile failed for an unexpected reason. If three retries fail, the user should contact Apple support.

For example, the server might send a response that looks like this:

HTTP/1.1 200 OK
Date: Thu, 9 May 2013 03:24:28 GMT
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Content-Length: 160
Connection: Keep-Alive
 
{
    "profile_uuid": "88fc4e378fea4021a94b2d7268fbf767",
    "devices": {
                  "C8TJ500QF1MN":"SUCCESS",
                  "B7CJ500QF1MA":"NOT_ACCESSIBLE"
               }
}
Request-Specific Errors

In addition to the standard errors listed in Common Error Codes, this request can return the following errors:

  • A 400 error with DEVICE_ID_REQUIRED in the body of the response indicates that the request did not contain any device IDs.

  • A 400 error with PROFILE_UUID_REQUIRED in the body of the response indicates that the request did not contain a profile ID.

  • A 404 error with PROFILE_NOT_FOUND in the body of the response indicates that the profile with the specified UUID could not be found.

Fetch Profile

Returns information about a profile.

URL

https://mdmenrollment.apple.com/profile

Query Type

GET

Request Query

The query string should contain the following keys:

Key

Value

profile_uuid

The UUID of a profile.

For example, your MDM server might make the following request:

GET /profile?profile_uuid=3dd2ccafe97bf07130fe3c908a92c870 HTTP/1.1
User-Agent:ProfileManager-1.0
X-Server-Protocol-Version:2
Content-Length: 0
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Response Body

In response, the MDM enrollment service returns a JSON dictionary with the following keys:

Key

Value

profile_name

String. A human-readable name for the profile.

profile_uuid

String. The unique ID of the assigned profile.

url

String. The URL of the MDM server.

allow_pairing

Optional. Boolean. Default is true.

is_supervised

Optional. Boolean. If true, the device must be supervised. Defaults to false.

is_multi_user

Optional. Boolean. If true, tells the device to configure for Shared iPad. Default is false. This key is valid in X-Server-Protocol-Version 2 and later.

Devices that do not meet the Shared iPad minimum requirements do not honor this command. With iOS devices, com.apple.mdm.per-user-connections must be added to the MDM enrollment profile’s ServerCapabilities. See iOS Support for Per-User Connections.

is_mandatory

Optional. Boolean. If true, the user may not skip applying the profile returned by the MDM server. Default is false.

await_device_configured

Optional. Boolean. If true, the device will not continue in Setup Assistant until the MDM server sends a command stating that the device is configured (see DeviceConfigured). Default is false. This key is valid in X-Server-Protocol-Version 2 and later.

is_mdm_removable

If false, the MDM payload delivered by the configuration URL cannot be removed by the user using the user interface on the device; that is, the MDM payload is locked onto the device. Defaults to true.

support_phone_number

Optional. String. A support phone number for the organization.

support_email_address

Optional. String. A support email address for the organization. This key is valid in X-Server-Protocol-Version 2 and later.

org_magic

A string that uniquely identifies various services that are managed by a single organization.

anchor_certs

Optional. Array of strings. Each string should contain a DER-encoded certificate converted to Base64 encoding. If provided, these certificates are used as trusted anchor certificates when evaluating the trust of the connection to the MDM server URL. Otherwise, the built-in root certificates are used.

supervising_host_certs

Optional. Array of strings. Each string contains a DER-encoded certificate converted to Base64 encoding. If provided, the device will continue to pair with a host possessing one of these certificates even when allow_pairing is set to false.

skip_setup_items

Optional. Array of strings. A list of setup panes to skip. The array may contain one or more of the following strings:

  • Passcode: Hides and disables the passcode pane.

  • Registration: Disables registration screen in macOS.

  • Location: Disables Location Services.

  • Restore: Disables restoring from backup.

  • AppleID: Disables signing in to Apple ID and iCloud.

  • Biometric: Skips Touch ID setup.

  • Payment: Skips Apple Pay setup.

  • Zoom: Skips zoom setup.

  • DisplayTone: Skips DisplayTone setup.

  • Android: If the Restore pane is not skipped, removes Move from Android option from it.

  • TOS: Skips Terms and Conditions.

  • Siri: Disables Siri.

  • Diagnostics: Disables automatically sending diagnostic information.

  • HomeButtonSensitivity: Skips the Home Button screen.

  • FileVault: Disables FileVault Setup Assistant screen.

  • TapToSetup: Skips the Tap To Set Up option in ATV about using an iOS device to set up your ATV (instead of entering all your account information and setting choices separately).

  • ScreenSaver: Skips the tvOS screen about using aerial screensavers in ATV (instead of entering all your account information and setting choices separately).

department

Optional. The user-defined department or location name.

For example, the server might send a response that looks like this:

HTTP/1.1 200 OK
Date: Thu, 28 Feb 2013 02:24:28 GMT
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Content-Length: 160
Connection: Keep-Alive
 
{
   "profile_uuid": "88fc4e378fea4021a94b2d7268fbf767",
   "profile_name": "Test Profile",
   "url":"https://mdm.acmeinc.com/getconfig",
   "is_supervised":false,
   "allow_pairing":true,
   "is_mandatory":false,
   "await_device_configured":false,
   "is_mdm_removable":false,
   "department": "IT Department",
   "org_magic": "913FABBB-0032-4E13-9966-D6BBAC900331",
   "support_phone_number": "1-555-555-5555",
   "support_email_address": "org-email@example.com",
   "anchor_certs":[
      "MIICkDCCAfmgAwIBAgIJAOAeuvyohALaMA0GCSqGSIb3DQEBBQUAMGExCzAJBgNVBAYT..."
   ],
   "supervising_host_certs:[
        "AlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJQ3VwZXJ0aW5vMRowGAYDVQQKDBFB…"
    ],
   "skip_setup_items":[
      "Location",
      "Restore",
      "Android",
      "AppleID",
      "TOS",
      "Siri",
      "Diagnostics",
      "Biometric",
      "Payment",
      "Zoom",
      "FileVault",
      "TapToSetup",
      "ScreenSaver"
   ]
}
Request-Specific Errors

In addition to the standard errors listed in Common Error Codes, this request can return the following errors:

  • A 400 error with PROFILE_UUID_REQUIRED in the body of the response indicates that the request did not contain a profile UUID.

  • A 404 error with PROFILE_NOT_FOUND in the body of the response indicates that a profile cannot be found for the requested profile UUID.

Request to a Profile URL

When a url value is provided in the profile response, the device makes an HTTPS POST call to that URL. The requesthas a Content-Type of application/pkcs7-signature. The following dictionary is sent as the body of the request. The dictionary is encoded as an XML plist and then CMS-signed and DER-encoded:

Field

Type

Content

UDID

String

The device’s UDID.

SERIAL

String

The device’s serial number.

PRODUCT

String

The device’s product type: e.g., iPhone5,1.

VERSION

String

The OS version installed on the device: e.g., 7A182.

IMEI

String

The device’s IMEI (if available).

MEID

String

The device’s MEID (if available).

LANGUAGE

String

The user’s currently-selected language: e.g., en.

The plist is CMS-signed with the device identity certificate. The device’s certificate and all necessary intermediate certificates are included. The certificate chain should validate against the Apple Root CA.

The server may respond with a 401 (Unauthorized) status message to prompt the user for a login. If this response is sent, the WWW-Authenticate header must contain the Digest authentication method. In iOS 7.1, the WWW-Authenticate header may also contain the Basic authentication method as outlined in RFC2617. When the user enters a username and password, the request is retried with the appropriate Authorization header.

If a 401 status is sent, the content of the response is shown above the prompt for the username and password. If the content is empty, a default message is displayed.

The server may respond with a 200 (OK) status to indicate a successful retrieval of the configuration profile. The configuration profile containing the MDM payload and one or more SCEP or certificate payloads must be included in the message body.

Remove Profile

Removes profile mapping from the list of devices from Apple’s servers. After this call, the devices in the list will have no profiles associated with them. However, if those devices have already obtained the profile, this has no effect until the device is wiped and activated again.

URL

https://mdmenrollment.apple.com/profile/devices

Query Type

DELETE

Request Body

The request body should contain a JSON dictionary with the following keys:

Key

Value

devices

Array of strings containing device serial numbers.

For example, your MDM server might make the following request:

DELETE /profile/devices HTTP/1.1
User-Agent:ProfileManager-1.0
X-Server-Protocol-Version:2
Content-Type: application/json;charset=UTF8
Content-Length: 35
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
 
{
    "devices":["C8TJ500QF1MN", "B7CJ500QF1MA"]
}
Response Body

In response, the MDM enrollment service returns a JSON dictionary with the following keys:

Key

Value

devices

A dictionary of devices. Each key in this dictionary is the serial number of a device in the original request. Each value in this dictionary is one of the following strings:

  • SUCCESS: Profile was removed from the device.

  • NOT_ACCESSIBLE: A device with the specified serial number was not found.

  • FAILED: Removing the profile failed for an unexpected reason. If three retries fail, the user should contact Apple support.

For example, the server might send a response that looks like this:

HTTP/1.1 200 OK
Date: Thu, 9 May 2013 03:24:28 GMT
Content-Type: application/json;charset=UTF8
X-ADM-Auth-Session: 87a235815b8d6661ac73329f75815b8d6661ac73329f815
Content-Length: 160
Connection: Keep-Alive
 
{
    "devices": {
                  "C8TJ500QF1MN":"SUCCESS",
                  "B7CJ500QF1MA":"NOT_ACCESSIBLE"
               }
}
Request-Specific Errors

In addition to the standard errors listed in Common Error Codes, this request can return the following errors:

  • A 400 error with DEVICE_ID_REQUIRED in the body of the response indicates that the request did not contain any device serial numbers.

Common Error Codes

If the request could not be validated, the server returns one of the following errors.

For example, the following is the response when an authentication token has expired.

HTTP/1.1 401 Unauthorized
Content-Type: text/plain;Charset=UTF8
Content-Length: 12
Date: Thu, 31 May 2012 21:23:57 GMT
Connection: close
 
UNAUTHORIZED

After a period of extended inactivity, this token expires, and the MDM server must obtain a new auth token from the https://mdmenrollment.apple.com/session endpoint.

All responses may return a new X-ADM-Auth-Session token, which the MDM server should use in subsequent requests.