Developer Console

Request an Access Token

Before you can use Amazon Device Messaging (ADM) to send a message to an instance of your app, on the server side you must have:

  • Obtained and stored the app instance's registration ID; for more details, see Integrate Your App.
  • Exchanged your OAuth client credentials for a current access token. This document describes that process.

To send a message and for information about the high-level architecture of ADM, see Send a Message and Overview of ADM.

Client credentials and access tokens

To acquire an access token, your server provides ADM servers with your OAuth client credentials. Your client credentials are assigned to you by Amazon and are two pieces of data that are unique to your app: a client_id and a client_secret value. Your servers use both pieces of your client credentials in their requests to obtain ADM access tokens. For information about how to get your client credentials, see Obtain Credentials.

An access token is short-lived metadata that authenticates your server's identity to ADM, so that you can send messages. When you send a message using ADM, that message request must include an access token. Although a server only uses a single access token at any given time, you must obtain a new access token when an old one expires. Also, although it is possible to share an access token across multiple servers, it is typically more convenient for each of your servers to obtain their own access token and independently request, track, and use it for sending messages.

Request format

Your servers obtain their access tokens by providing your client credentials in a request call to ADM servers. You can use this same request to acquire an initial access token or to obtain a new one when a prior access token has expired.

To obtain an access token, your server issues a POST request on an HTTPS connection. The request looks similar to this:

POST /auth/O2/token HTTP/1.1
Host: api.amazon.com
Content-Type: application/x-www-form-urlencoded;charset=UTF-8

grant_type=client_credentials&scope=messaging:push&client_id=(YOUR_CLIENT_ID)&client_secret=(YOUR_CLIENT_SECRET)

The request itself consists of two parts: a header and a message body. The header must contain the following field:

Field Description Example
Content-Type The content type of the resource. Must be: application/x-www-form-urlencoded Content-Type: application/x-www-form-urlencoded

For the content of the message body, you must provide a URL-encoded string containing the following parameters:

Parameter Description Example
grant_type Value must be client_credentials grant_type=client_credentials
scope Value must be messaging:push scope=messaging:push
client_id The "client identifier" portion of your client credentials. client_id=amzn1.iba-client.<hexidecimal client credentials>
client_secret The "client secret" portion of your client credentials. client_secret=<YOUR_CLIENT_SECRET>

Response format

After successfully receiving and interpreting your POST request message, ADM sends your server an HTTP response message that looks similar to this:

X-Amzn-RequestId: <client ID>
Content-Type: application/json

{
  "access_token":"Atc|<client access token>",
  "expires_in":3600,
  "scope":"messaging:push",
  "token_type":"Bearer"
}

The header for the response contains the following fields:

Header Description Example
X-Amzn-RequestId A value created by ADM that uniquely identifies the request. In the unlikely event that you have problems with ADM, Amazon can use this value to troubleshoot the problem. X-Amzn-RequestId: <hexidecimal request ID>
Content-Type The content type of the resource: application/json Content-Type: application/json

When one of your servers successfully requests an access token you receive a 200 status code response, and the message body for the response to that request includes both the access token and its lifespan in seconds.

Parameter Description Example
access_token An access token that must be used for all enqueue requests. "access_token":"<hexidecimal access token>"
expires_in The duration in seconds of the access token lifetime. For example, the value "3600" denotes that the access token expires in one hour from the time the response was generated. "expires_in":3600
token_type The type of the token issued. One of the supported token types. Currently only "Bearer" tokens are supported. "token_type":"Bearer"
scope The scope specified in the access token request. Value will be messaging:push. "scope":"messaging:push"

ADM returns a non-200 error status code for an unsuccessful request. In the case of a non-200 code, the response message might contain the following parameter in the body of the JSONObject:

  • reason: The reason the request was not accepted.

The following table lists possible error status codes for an access token request.

Code Description Example
400 Reasons for this response include: * The content type is not supported by the authorization server. In other words, it is not application/x-www-form-urlencoded. * The request is missing a required parameter: client_id, client_secret, scope, grant-type. * The request is otherwise malformed. * ADM has not been enabled for your security profile. See Obtain Credentials. INVALID_REQUEST
400 The client is not authorized for the requested operation. UNAUTHORIZED_CLIENT
400 The grant type is not supported by the authorization server. In other words, it is not client_credentials. UNSUPPORTED_GRANT_TYPE
400 The requested scope is invalid. In other words, it is not messaging:push. INVALID_SCOPE
401 The client authentication failed. INVALID_CLIENT
500 There was an internal server error. The requester can retry the request. SERVER_ERROR
503 The server is temporarily unavailable. The requester must retry later honoring the Retry-After header included in the response. See the HTTP/1.1 specification, section 14.37, for possible formats for the Retry-After value. SERVICE_UNAVAILABLE

Making the token request and handling the response

The following code sample is an example of how your server software might send the access token request and handle the ADM servers' response:

/**
  * To obtain an access token, make an HTTPS request to Amazon
  * and include your client_id and client_secret values.
  */
public String getAuthToken(String clientId, String clientSecret) throws Exception
{
     // Encode the body of your request, including your clientID and clientSecret values.
     String body = "grant_type="    + URLEncoder.encode("client_credentials", "UTF-8") + "&" +
                   "scope="         + URLEncoder.encode("messaging:push", "UTF-8")     + "&" +
                   "client_id="     + URLEncoder.encode(clientId, "UTF-8")             + "&" +
                   "client_secret=" + URLEncoder.encode(clientSecret, "UTF-8");

     // Create a new URL object with the base URL for the access token request.
     URL authUrl = new URL("https://api.amazon.com/auth/O2/token");

     // Generate the HTTPS connection. You cannot make a connection over HTTP.
     HttpsURLConnection con = (HttpsURLConnection) authUrl.openConnection();
     con.setDoOutput( true );
     con.setRequestMethod( "POST" );

     // Set the Content-Type header.
     con.setRequestProperty( "Content-Type" , "application/x-www-form-urlencoded" );
     con.setRequestProperty( "Charset" , "UTF-8" );
     // Send the encoded parameters on the connection.
     OutputStream os = con.getOutputStream();
     os.write(body.getBytes( "UTF-8" ));
     os.flush();
     con.connect();

     // Convert the response into a String object.
     String responseContent = parseResponse(con.getInputStream());

     // Create a new JSONObject to hold the access token and extract
     // the token from the response.
     org.json. JSONObject parsedObject = new org.json.JSONObject(responseContent);
     String accessToken = parsedObject.getString("access_token");
     return accessToken;
}

private String parseResponse(InputStream in) throws Exception
{
     InputStreamReader inputStream = new InputStreamReader(in, "UTF-8" );
     BufferedReader buff = new BufferedReader(inputStream);

     StringBuilder sb = new StringBuilder();
     String line = buff.readLine();
     while (line != null )
     {
       sb.append(line);
       line = buff.readLine();
     }

     return sb.toString();
}

Last updated: Sep 21, 2022