> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://developer.americanexpress.ferndocs.com/fraud-prevention/v2/amex-token-service/api-reference/provision-a-token/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.americanexpress.ferndocs.com/_mcp/server. # Provision a token. POST https://api.qa.americanexpress.com/payments/digital/v2/tokens/provisionings Content-Type: application/json Returns the token and displays the account information if valid details are provided for a given Card. Reference: https://developer.americanexpress.ferndocs.com/fraud-prevention/amex-token-service/api-reference/provision-a-token ## Authentication - `Authorization` header (required) — HMAC (one-way TLS). A `MAC` authorization header signed with your client secret. See https://developer.americanexpress.com/documentation/api-security/hmac ## Servers - `https://api.qa.americanexpress.com/payments/digital/v2/tokens` (Sandbox, default) - `https://api.americanexpress.com/payments/digital/v2/tokens` (Production) ## Request ### Headers - `Accept-Language` (string, required) — This is en-US. - `Content-Language` (string, required) — This is en-US. - `Authorization` (string, required) — The HMAC authorization header generated as prescribed by American Express API security.e.g., MAC id="OLQkWT14WtLR0aE63AqtkW2DJppMviSk", ts="1548353658039", nonce="18036bb8-a100-4e02-ab93-328abd67acf2", bodyhash="uRphuQfK6igW44z4Ns/Bo9XdiXlsCdEzTsxdeUBu9j8=", mac="yJ70ObsprC2ygCjzq88Lq0QTKPqlLMIPYpR4O1DBg+Y=" - `x-amex-api-key` (string, required) — The Client ID displayed on the American Express Token Service dashboard.e.g., OLQkWT14WtLR0aE63AqtkW2DJppMviSk - `x-amex-token-requester-id` (string, required) — The unique identifier as a Token Requester. Available on the American Express Token Service dashboard.e.g., devportalTest - `x-amex-request-id` (string, required) — The unique identifier for the API request to be returned in the response headers.It is set by the API caller, and should never be re-used across different transactions.e.g., AA3434342323 ### Body (application/json) This endpoint expects a provisionings_request. - `account_data` (provisionings_account_data, optional) — The base64-encoded JWE string containing the Primary Account Number (PAN) information. The JWE string should adhere to RFC 7516.Steps for encryption:The JWE encryption utility will generate an AES 128-bit dynamic data encryption key. Encrypt the account_data object using this key and the A128GCM algorithm.The dynamic data encryption key should be wrapped with the static AES 256-bit key provided by American Express using the A256KW algorithm.Set the key identifier of the static AES key in the header.Use the JSON compact serialization.Set the resulting JWE blob in the account_data element.Key wrap algorithm: A256KWData encryption algorithm: AES/GCM/NoPadding - `risk_assessment_data` (risk_assessment_data, optional) — The User's risk profile on the Token Requester's domain. - `user_data` (user_data, optional) — The User's profile information on the Token Requester's domain. ## Response ### 200 The request has been processed successfully.Upon a 200 response, the token is successfully provisioned and the token data is returned in a response payload. - `token_ref_id` (string, optional) — The unique reference identifier for a token.NOTE: This data needs to be stored by the Token Requester for the life cycle API calls, such as /notifications, /status, and /metadata. - `secure_token_data` (ProvisioningsSuccessResponseSecureTokenData, optional) — The JSON Web-encrypted token and payment data for authorization. You will receive this as a base64-encoded string as per RFC 7516. The secure_token_data is encrypted using a dynamically-generated, 128-bit data encryption key using the A128GCM algorithm. The dynamic data encryption key is wrapped with the static AES 256-bit key provided by American Express, using the A256KW algorithm.Steps to decrypt:Base64 decodes the header and reads the key identifier. Looks up the static AES 256-bit key provided by American Express that has been mapped to the key identifier.Unwraps the dynamic data encryption key, using the static AES 256-bit key, by means of the A256KW algorithm.Decrypts the data using the 128-bit dynamic encryption key, by means of the A128GCM algorithm.Validates the authorization tag.The resulting JSON object conforms to the secure_token_data.Key wrap algorithm: A256KWData encryption algorithm: AES/GCM/NoPadding - `account_metadata` (account_metadata, optional) — This is only meant to be used to enrich the display. - `issuer_data` (issuer_data, optional) — The meta-data for the Card's account as provided by the Card's Issuer. This data is only meant to be used for enriching the display of Card's account. ## Errors ### 400 Bad Request Error The submitted request body is not valid. - `error_code` (string, optional) — An error code indicating the contents of the request body that triggered an error.e.g., 104000 - `error_type` (string, optional) — An error type specifying the type of error triggered for the given request body.e.g., invalid_json_error - `error_description` (string, optional) — An error description specifying the problem with the provided request body.e.g., request_body_not_parseable_json ### 401 Unauthorized Error The Authorization header sent with the given request failed internal validation checks. - `error_code` (string, optional) — An error code indicating the request was rejected due to an incorrect Authorization header value.e.g., 104010 - `error_type` (string, optional) — An error type specifying that the type of error triggered was related to the request's Authorization field using HMAC.e.g., invalid_hmac - `error_description` (string, optional) — An error description specifying that the received request's Authorization header does not align with the provided request body or has been generated incorrectly.e.g., invalid_hmac ### 429 Too Many Requests Error The rate at which the caller is allowed to call the service has been exceeded. The caller request rate should be reduced. - `error_code` (string, optional) — An error code indicating the request was rejected due to the frequency of requests to the API.e.g., 104290 - `error_type` (string, optional) — An error type indicating the request was rejected due to the rate of requests being sent by the Token Requester.e.g., rate_limit_violation - `error_description` (string, optional) — An error description indicating the request was rejected due to the rate at which requests are sent to the API exceeding the established request rate limit.e.g., rate_limit_exceeded ### 500 Internal Server Error Internal error. An error that has occurred within the American Express system. The request may be retried based on the aligned retry policy. - `error_code` (string, optional) — An error code indicating the request was rejected due to an error within the API.e.g., 105000 - `error_type` (string, optional) — An error type indicating the request was rejected due to a transient failure within the API.e.g., system_error - `error_description` (string, optional) — An error description indicating the request failed due to an internal issue with the API.e.g., internal_api_error ### 504 Gateway Timeout Error The API gateway has experienced a connection timeout. The request may be retried based on the aligned retry policy. - `error_code` (string, optional) — An error code indicating the request did not receive a response due to a timeout from the API.e.g., 105040 - `error_type` (string, optional) — An error type indicating the request failed to receive its response due to a timeout from the API.e.g., connection_timeout - `error_description` (string, optional) — An error description indicating the request failed to receive a response from the API due to a connection timeout.e.g., connection_timeout ## Types ### provisionings_account_data The base64-encoded JWE string containing the Primary Account Number (PAN) information. The JWE string should adhere to RFC 7516.Steps for encryption:The JWE encryption utility will generate an AES 128-bit dynamic data encryption key. Encrypt the account_data object using this key and the A128GCM algorithm.The dynamic data encryption key should be wrapped with the static AES 256-bit key provided by American Express using the A256KW algorithm.Set the key identifier of the static AES key in the header.Use the JSON compact serialization.Set the resulting JWE blob in the account_data element.Key wrap algorithm: A256KWData encryption algorithm: AES/GCM/NoPadding - `account_type` (string, optional) — Specifies the type of account. The value should be set to credit_card. - `credit_card` (credit_card, optional) — The Credit Card information. - `billing_address` (billing_address, optional) — The Card Member's billing address fields. - `authentication_method` (authentication_method, optional) — India Market Only: Mandatory for India merchants provisioning India cards. Not for use in other markets. ### risk_assessment_data The User's risk profile on the Token Requester's domain. - `account_input_method` (string, optional) — The mechanism by which the Card details were captured. The allowed values are:On file: If the Card details are on-file.User Input: If the User entered the Card details in the current session. - `pan_tenure_on_file` (string, optional) — The number of weeks since the User added the Card account details on file. - `ip_address` (string, optional) — The IPv6 or IPv4 address of the User's mobile device or browser. Required when the account_input_method is User Input.e.g.,IPv4: 111.111.111.1111IPv6: ABCD:ABCD:ABCD:ABCD:ABCD:ABCD:ABCD:ABCD ### user_data The User's profile information on the Token Requester's domain. - `user_id` (string, optional) — The unique User identifier set by the Token Requester.e.g., 3307070056 - `phone` (string, optional) — The User's phone number. The phone number should start with + followed by a string of digits between zero and nine with a minimum length of 11 digits.e.g., +0011234567890NOTE: Either a phone number or an email address must be provided. The absence of both fields will return a missing field error. - `email` (string, optional) — A valid User email address when available. The email string should adhere to the RFC 5322 official standard.NOTE: Either a phone number or an email address must be provided. The absence of both fields will return a missing field error.e.g., [someone@example.com](mailto:someone@example.com) - `name` (string, optional) — The Card Holder's name. ### ProvisioningsSuccessResponseSecureTokenData The JSON Web-encrypted token and payment data for authorization. You will receive this as a base64-encoded string as per RFC 7516. The secure_token_data is encrypted using a dynamically-generated, 128-bit data encryption key using the A128GCM algorithm. The dynamic data encryption key is wrapped with the static AES 256-bit key provided by American Express, using the A256KW algorithm.Steps to decrypt:Base64 decodes the header and reads the key identifier. Looks up the static AES 256-bit key provided by American Express that has been mapped to the key identifier.Unwraps the dynamic data encryption key, using the static AES 256-bit key, by means of the A256KW algorithm.Decrypts the data using the 128-bit dynamic encryption key, by means of the A128GCM algorithm.Validates the authorization tag.The resulting JSON object conforms to the secure_token_data.Key wrap algorithm: A256KWData encryption algorithm: AES/GCM/NoPadding - `token_number` (string, optional) — The unique token number for the Card Account Number provided in the request.e.g., 343434343434343 - `expiry_month` (integer, optional) — The token's expiration month as an integer.e.g., 3 - `expiry_year` (integer, optional) — The token's expiration year as a four-digit (YYYY) integer.e.g., 2022 - `payment_account_reference` (string, optional) — The PAR is a unique non-financial alphanumeric EMVCo data element used to identify payment accounts across multiple form factors, not intended to be a payment replacement or a Consumer identifier, to assist non-payment use cases that rely on PAN. Since PAR persists through PAN life cycle changes, PAR provides better longevity as an identifier than the PAN. ### account_metadata This is only meant to be used to enrich the display. - `is_request_pan_latest` (boolean, optional) — Indicates if the account number in the request is current. - `display_account_number` (integer, optional) — The last four digits of the Card Account Number.e.g., 4324 - `account_country_code` (string, optional) — Based on the ISO 3166-1 two-digit, alphanumeric country code format.e.g., US - `card_art` (AccountMetadataCardArt, optional) — The Card's asset information. - `product_short_name` (string, optional) — The short name for the product on the provided Card. - `expiry_month` (integer, optional) — The Card's expiration month as an integer.e.g., 3 - `expiry_year` (integer, optional) — The Card's expiration year as a four-digit (YYYY) integer.e.g., 2022 ### issuer_data The meta-data for the Card's account as provided by the Card's Issuer. This data is only meant to be used for enriching the display of Card's account. - `logo_url` (string, optional) — The network logo URL of the Issuer of the Card.NOTE: Provided only for supported Issuers. - `name` (string, optional) — The legal name of the Card's Issuer. - `privacy_policy_url` (string, optional) — The URL for the privacy policy page of the Card's Issuer.NOTE: Provided only for supported Issuers. - `contact_number` (string, optional) — The contact number of the Card's Issuer. This number should be displayed on a wallet. - `website_url` (string, optional) — The URL for the website of the Card's Issuer.NOTE: Provided only for supported Issuers. - `email` (string, optional) — The email address of the Card's Issuer. This email is to be displayed on a wallet. - `icon` (string, optional) — For use in notifications. The size and resolution vary based on the Token Requester's needs.NOTE: Provided only if the Issuer supports this field. - `app_schemes` (IssuerDataAppSchemes, optional) — Requirements for applications. ### credit_card The Credit Card information. - `account_number` (string, optional) — The 15-digit primary Card Account Number. - `expiry_month` (integer, optional) — The Card's expiration month as an integer.e.g., 3 - `expiry_year` (integer, optional) — The Card's expiration year as a four-digit (YYYY) integer.e.g., 2022 ### billing_address The Card Member's billing address fields. - `address_line1` (string, optional) — Line one of the provided Card's billing address. - `address_line2` (string, optional) — Line two of the provided Card's billing address. - `address_line3` (string, optional) — Line three of the provided Card's billing address. - `city` (string, optional) — The billing address city of the provided Card. - `state` (string, optional) — The billing address state of the provided Card. - `postal_code` (string, optional) — The billing address postal code of the provided Card.NOTE: Required in countries where the postal code is available. - `country` (string, optional) — The billing address country of the provided Card.Based on the ISO 3166-1 two-digit, alphanumeric country code format.NOTE: If the billing address object is provided, a country code is required. ### authentication_method India Market Only: Mandatory for India merchants provisioning India cards. Not for use in other markets. - `method` (string, optional) — The cryptographic method by which validation was performed. The value should be set to "AEVV". - `value` (string, optional) — The cryptographic value provided for the chosen cryptographic validation method. ### AccountMetadataCardArt The Card's asset information. - `card_art_url` (string, optional) — The URL pointing to the Card's art image. The image format will be either SVG or PNG. - `foreground_color` (string, optional) — The text color to be displayed on the Card's artwork.e.g., rgb(0,0,0) ### IssuerDataAppSchemes Requirements for applications. - `os_type` (string, optional) — The operating system will be either iOS (Apple) or Android. - `scheme` (string, optional) — The native app URL or servicing scheme of the Card's Issuer.NOTE: This should contain the package/bundle identifier of the application. ## Examples **Request** ```json {} ``` **Response** ```json { "token_ref_id": "string", "secure_token_data": { "token_number": "string", "expiry_month": 1, "expiry_year": 1, "payment_account_reference": "string" }, "account_metadata": { "is_request_pan_latest": true, "display_account_number": 1, "account_country_code": "string", "card_art": { "card_art_url": "string", "foreground_color": "string" }, "product_short_name": "string", "expiry_month": 1, "expiry_year": 1 }, "issuer_data": { "logo_url": "string", "name": "string", "privacy_policy_url": "string", "contact_number": "string", "website_url": "string", "email": "string", "icon": "string", "app_schemes": { "os_type": "string", "scheme": "string" } } } ``` **SDK Code** ```python import requests url = "https://api.qa.americanexpress.com/payments/digital/v2/tokens/provisionings" payload = {} headers = { "Accept-Language": "Accept-Language", "Authorization": "", "Content-Language": "Content-Language", "x-amex-api-key": "x-amex-api-key", "x-amex-request-id": "x-amex-request-id", "x-amex-token-requester-id": "x-amex-token-requester-id", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = 'https://api.qa.americanexpress.com/payments/digital/v2/tokens/provisionings'; const options = { method: 'POST', headers: { 'Accept-Language': 'Accept-Language', Authorization: '', 'Content-Language': 'Content-Language', 'x-amex-api-key': 'x-amex-api-key', 'x-amex-request-id': 'x-amex-request-id', 'x-amex-token-requester-id': 'x-amex-token-requester-id', 'Content-Type': 'application/json' }, body: '{}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.qa.americanexpress.com/payments/digital/v2/tokens/provisionings" payload := strings.NewReader("{}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Accept-Language", "Accept-Language") req.Header.Add("Authorization", "") req.Header.Add("Content-Language", "Content-Language") req.Header.Add("x-amex-api-key", "x-amex-api-key") req.Header.Add("x-amex-request-id", "x-amex-request-id") req.Header.Add("x-amex-token-requester-id", "x-amex-token-requester-id") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby require 'uri' require 'net/http' url = URI("https://api.qa.americanexpress.com/payments/digital/v2/tokens/provisionings") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Accept-Language"] = 'Accept-Language' request["Authorization"] = '' request["Content-Language"] = 'Content-Language' request["x-amex-api-key"] = 'x-amex-api-key' request["x-amex-request-id"] = 'x-amex-request-id' request["x-amex-token-requester-id"] = 'x-amex-token-requester-id' request["Content-Type"] = 'application/json' request.body = "{}" response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.qa.americanexpress.com/payments/digital/v2/tokens/provisionings") .header("Accept-Language", "Accept-Language") .header("Authorization", "") .header("Content-Language", "Content-Language") .header("x-amex-api-key", "x-amex-api-key") .header("x-amex-request-id", "x-amex-request-id") .header("x-amex-token-requester-id", "x-amex-token-requester-id") .header("Content-Type", "application/json") .body("{}") .asString(); ``` ```php request('POST', 'https://api.qa.americanexpress.com/payments/digital/v2/tokens/provisionings', [ 'body' => '{}', 'headers' => [ 'Accept-Language' => 'Accept-Language', 'Authorization' => '', 'Content-Language' => 'Content-Language', 'Content-Type' => 'application/json', 'x-amex-api-key' => 'x-amex-api-key', 'x-amex-request-id' => 'x-amex-request-id', 'x-amex-token-requester-id' => 'x-amex-token-requester-id', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://api.qa.americanexpress.com/payments/digital/v2/tokens/provisionings"); var request = new RestRequest(Method.POST); request.AddHeader("Accept-Language", "Accept-Language"); request.AddHeader("Authorization", ""); request.AddHeader("Content-Language", "Content-Language"); request.AddHeader("x-amex-api-key", "x-amex-api-key"); request.AddHeader("x-amex-request-id", "x-amex-request-id"); request.AddHeader("x-amex-token-requester-id", "x-amex-token-requester-id"); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = [ "Accept-Language": "Accept-Language", "Authorization": "", "Content-Language": "Content-Language", "x-amex-api-key": "x-amex-api-key", "x-amex-request-id": "x-amex-request-id", "x-amex-token-requester-id": "x-amex-token-requester-id", "Content-Type": "application/json" ] let parameters = [] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.qa.americanexpress.com/payments/digital/v2/tokens/provisionings")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ```