Make Adaptive Planning API Requests with Workday Credentials
Workday-synchronized users who log in to Workday and use the Worklet can run public APIs. Users must create an ISU specifically for making these API requests. These users must provide a token in the
credentials
element of API requests instead of a username and password. You can cache this token and use it until it expires. After it expires, you must get a new token.Workday Domain and Security Groups
- Verify the ISU users who need API access are part of theSet Up: Adaptive Planning API Accesssecurity domain.
Workday Setup Tasks
- Verify thatSingle Sign-Ontasks are enabled within theUser Sign-ontab in the tab.
- Verify thePublic API setuptask is enabled within thePublic APItab in the tab.
- Verify an integration system user (ISU) setup task created an ISU specifically for making Workday Adaptive Planning API requests and mapped it to an user account.
User Admin
- Verify you see the ISU beginning withPublicAPIISU_in the users list within Administration > Users.
- Verify this user has the level access needed for the APIs they want to run. New ISUs don't receive level access by default.
- Get a Certificate and Extract your Public Key.
- Register an API Client in Workday with that certificate.
- Generate a JWT Token, Retrieve Workday access_token, and Retrieve AdaptiveAPIAccessToken.
- Use the AdaptiveAPIAccessToken in an API Request.
Get a Certificate and Extract your Public Key
You can create a certificate yourself or purchase a certificate from a well-known certificate authority. For the details on the parameters needed for your X.509 Certificate in Workday, see Concept: X.509 Certificates in Workday.
- Extract the public key from your certificate for uploading to Workday.
- Retain your private key for use in your calling application.
- Paste the certificate into Workday when registering your JWT bearer token. Reference your private key in your script.
Register a Workday API Client
- Register an API Client withClient Grant Type: Jwt Bearer Grantin Workday. See Register an API Client for more information.
- Copy the public key derived for your certificate into thex.509 Certificatein the Register API Client page in Workday.
- ForScope (Functional Area)select.
- When you finish registering the API client, copy the resulting fields at the bottom of the page to a text file to use later.
- Workday REST API Endpoint
- Token Endpoint
- Authorization Endpoint
Generate JWT Token, Retrieve Workday access_token, and Retrieve AdaptiveAPIAccessToken
- Use your private key and generate the JWT token by running pseudo code listed below.
- To retrieve a Workday access token, make aPOSTrequest to the Token Endpoint, passinggrant_typeandassertion. Use the Token Endpoint copied after registering your API client in Workday. Example Token Endpoint:https://{host or gateway}/ccx/oauth2/{tenant}/tokenExampleCURLrequest to the Token Endpointcurl --request POST 'https://{host or gateway}/ccx/oauth2/{tenant}/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' \ --data-urlencode 'assertion={{the jwt assertion from your certificate}}'
- Retrieve the AdaptiveAPIAccessToken by calling the Workday endpoint using the Workday access token. Use the prioraccess_tokenvalue as the Bearer token in theAuthheader for thisGET.Example Access Token:https://{host or gateway}/ccx/api/planning/v1/{tenant}/adaptiveAPIAccessTokenExampleCURLrequest for the AdaptiveAPIAccessToken:curl --request GET 'https://{host or gateway}/ccx/api/planning/v1/{tenant}/adaptiveAPIAccessToken' \ --header 'Authorization: Bearer {{the jwt assertion from your certificate}}' \ --data-raw ''
- Call the API using the AdaptiveAPIAccessToken in the credentials element of the XML in an HTTPPOST. Example:curl -H "Content-Type: text/xml" -d '<?xml version='1.0' encoding='UTF-8'?><call method="exportLevels" callerName="a string that identifies your client application"><credentials token="ID eyJhbDci0iJSUzUxMiIsUmtpZCI6IdvcmtkYXlfa2V5In0.eyJpc3KiOiJXb3JrZGFZIiwiYXV0aF90aW1lIjoxNTczMTY3NjU2LBjzeXnfynnJd.bztQzBmHeTj1amnHA-r96TdrJK0MXMghUFF1KyjxqIq6ruHU63dJp3JAJn3Eche7SEcoZBVGX4wJgna106pmCqgrrVWMf13Hg_sb_szabal2XN1KEEk1qh8z1IDlbt6qJIL_xyW3J2nNSs5ima3vJUYU5sRQXwXst0GuFWXpy464GyB4oKcscrg28X3dnPO_ytdohMKHsWkqyHQKXFQwoQezFaGy10sp4RRUj0lpOZX8C9oBHDYA58IXxGkqKLJVNPvDND6rGY5fTHQ-yxpe1nz-WqB0boiq9a-dv8b3EBzbelxj2fCPdMbng6kzygDcA2at_7BNQiyzfIovS5AG"/><include versionID="3" inaccessibleValues="false"/><sheet id="3" /></call>' -X POST https://api.adaptiveplanning.com/api/v23
Sample Java Application for Generating a JWT Token
This sample Java application generates a JWT token.
//********************************************************************** // // File: TestPublicAPISample.java // // Copyright 2004-2019 Workday Adaptive Planning. // All Rights Reserved. // // This work contains trade secrets and confidential material of // Workday Adaptive Planning and its use or disclosure in whole or in part // without the express written permission of Workday Adaptive Planning is prohibited. // //********************************************************************** import java.io.FileInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Signature; import java.text.MessageFormat; //import java.util.Base64; import org.apache.commons.codec.binary.Base64; public class AccessAdaptiveAPI { public static void main(String args[]) { String jwtKeyStoreFileString = "/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib/security/JWTkeystore.jks"; String clientIDString = "BlywNDM1NmMtZTk2Mi00NTZiTWEyZjktZWM1NGJiOGQ3Yjca"; String userIdString = "PublicAPIISU_Test"; System.out.println(GetAccessToken(clientIDString,userIdString,jwtKeyStoreFileString)); } public void callAPI() { } public String getAdaptiveAPIToken() { return ""; } public String getJWTToken(String privateKey, String username) { return ""; } public void callWorkdayAPI() { } public static String GetAccessToken(String clientId, String userId, String jwtKeyStore) { String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}"; String claimTemplate = "'{'\"iss\": \"{0}\", \"sub\": \"{1}\", \"aud\": \"{2}\", \"exp\": \"{3}\"'}'"; try { StringBuffer token = new StringBuffer(); //Encode the JWT Header and add it to our string to sign token.append(Base64.encodeBase64URLSafeString(header.getBytes("UTF-8"))); //Separate with a period token.append("."); //Create the JWT Claims Object String[] claimArray = new String[4]; //iss claimArray[0] = clientId; //sub claimArray[1] = userId; //aud claimArray[2] = "wd"; //exp claimArray[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300); MessageFormat claims; claims = new MessageFormat(claimTemplate); String payload = claims.format(claimArray); //Add the encoded claims object token.append(Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8"))); //token.append(Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8"))); //Load the private key from a keystore KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(jwtKeyStore), "Workday123!".toCharArray()); PrivateKey privateKey = (PrivateKey) keystore.getKey("Workday", "Workday123!".toCharArray()); //Sign the JWT Header + "." + JWT Claims Object Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(token.toString().getBytes("UTF-8")); String signedPayload = Base64.encodeBase64URLSafeString(signature.sign()); //Separate with a period token.append("."); //Add the encoded signature token.append(signedPayload); return token.toString(); //System.out.println(token.toString()); } catch (Exception e) { e.printStackTrace(); } return ""; } }
Sample C# Application for Generating a JWT Token
This sample C# application generates a JWT token that replaces the username and password in the credentials element of an API request.
This sample code requires a NuGet page. Required NuGet package:
System.IdentityModel.Tokens.Jwt
var clientId = "BlywNDM1NmMtZTk2Mi00NTZiTWEyZjktZWM1NGJiOGQ3Yjca";//Client ID from workday API Client var isu = "PublicAPIISU_Test"; //the ISU var timeout = (DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() / 1000 + 300).ToString(CultureInfo.InvariantCulture); var environment = "wd"; var pfxFilePath = @"C:\temp\JWTkeystore2.pfx"; var pfxPassword = "Workday123!"; var payload = new JwtPayload { {"iss", clientId}, {"sub", isu}, {"aud", environment}, {"exp", timeout }, }; var signingCredentials = new X509SigningCredentials(new X509Certificate2(pfxFilePath, pfxPassword), SecurityAlgorithms.RsaSha256); // the matching PKCS #12 file with private key var jwtHeader = new JwtHeader(signingCredentials); var secToken = new JwtSecurityToken(jwtHeader, payload); var handler = new JwtSecurityTokenHandler(); var tokenToWorkday = handler.WriteToken(secToken); Console.WriteLine(tokenToWorkday);
Use the AdaptiveAPIAccessToken in an API Request
Once you set up Workday for public API access, the credentials element of API requests use the AdaptiveAPIAccessToken instead of a username and password. Basic authentication with username and password won't work. See Adaptive Planning REST API and API Methods for more.
Example AdaptiveAPIAccessToken in an API Request
<?xml version='1.0' encoding='UTF-8'?> <call method="exportLevels" callerName="a string that identifies your client application"> <credentials token="ID eyJhbDci0iJSUzUxMiIsUmtpZCI6IdvcmtkYXlfa2V5In0.eyJpc3KiOiJXb3JrZGFZIiwiYXV0aF90aW1lIjoxNTczMTY3NjU2LBjzeXnfynnJd.bztQzBmHeTj1amnHA-r96TdrJK0MXMghUFF1KyjxqIq6ruHU63dJp3JAJn3Eche7SEcoZBVGX4wJgna106pmCqgrrVWMf13Hg_sb_szabal2XN1KEEk1qh8z1IDlbt6qJIL_xyW3J2nNSs5ima3vJUYU5sRQXwXst0GuFWXpy464GyB4oKcscrg28X3dnPO_ytdohMKHsWkqyHQKXFQwoQezFaGy10sp4RRUj0lpOZX8C9oBHDYA58IXxGkqKLJVNPvDND6rGY5fTHQ-yxpe1nz-WqB0boiq9a-dv8b3EBzbelxj2fCPdMbng6kzygDcA2at_7BNQiyzfIovS5AG"/> <include versionID="3" inaccessibleValues="false"/> <sheet id="3" /> </call>