Skip to navigation

Authentication Guide

Start integrating your applications with Citi’s services — authentication, certificate setup, access tokens, and encryption.

View as Markdown
Important note on certificate requirements

Please ensure your Client SSL Certificate includes Extended Key Usage containing either both Server and Client Authentication or Client Authentication only on the Leaf node level. Some Certificate Authorities are now issuing certificates including Server Authentication Extended Key Usage only, but these are not acceptable for Client SSL certificate upload. Learn more here.

Important note on using the correct version of authentication

Citi’s APIs use various Authentication versions. Ensure that the Authentication version you are using for your API matches what is referenced in the OAS file.

Overview

This guide will cover the process to start integrating your applications with Citi’s services. The guide includes authentication, certificate setup, obtaining an access token, and encryption.

To get started using Citi’s APIs, you will need to complete these steps.

1

Create an account

Create an account on the Developer Portal. Skip this step if you’re already signed up and logged in.

2

Request access

Request access to documentation or the test environment for specific Citi APIs with your Citi Representative’s information. You can review the Marketplace to see what APIs are available.

3

Choose your integration

Choose how to integrate with Citi APIs. Many APIs have an SDK available. You can start by downloading the SDKs when available on the individual API reference pages or you can do your own direct integration.

4

Get your credentials

Retrieve your Client ID and Client Secret from the Credentials & Certificates tab of your dashboard.

5

Set up certificates

Set up your certificates on the Credentials & Certificates tab of your dashboard.

  1. Upload the public keys of your certificates.
  2. Download the Citi keys from the Citi certificates section.
6

Testing confirmation

Get confirmation from your implementation manager that your account is ready for testing.

7

Production confirmation

Once you have successfully completed testing, your implementation manager will set up your account for production.

If you do not know who your Citi representative is, email devsupport@citi.com.


Creating an account

For security purposes, you will need to register two developer accounts from your organization to complete the certificate upload process. One account should upload the public keys then another developer from your organization will receive an email to approve the upload.

You will need to create a developer account. To create an account:

1

Complete registration form

Complete and submit the sign up form.

2

Validate email

Look for a verification email in your inbox and click on the link provided.

3

Complete sign in

Complete the sign in and enter your one-time password.

Registration is complete only after the first login. If you experience issues completing registration, please contact developer support.

Once you register for an account, you will have access to documentation for Account Reporting and Payments. To access additional API documentation and to use any of the APIs in the testing and production environments, you can request access on the Solution pages accessible from Marketplace, or on specific documentation pages. Your Citi Representative will let you know once your account is ready for testing.

Once testing or production environment access is granted, your Client ID and Client Secret can be found on your dashboard under the Credentials & Certificates tab. Citi will use these credentials to authenticate requests.

Do store your API credentials in a secure location and away from any publicly accessible areas such as client-side code or GitHub.


Security

Citi uses TLS 1.2 encryption for secure communications with your application. In addition, API payloads are encrypted, and digital signatures verified using encryption and 2048-bit RSA keys. Citi offers the highest level of security for client data among our peers.

Check with your Implementation Manager on which encryption algorithm to use with your API.

The following certificates must be installed on your server and the public key configured from the Credentials & Certificates tab on your dashboard.


Authentication endpoints

Citi currently supports four versions of the Authentication endpoint: V1, V2, V3, and V4. Please see the API Reference for specific information on calling the Authentication endpoint.

API-specific authentication information is provided as part of the authentication section in each API (i.e. which version of the authentication endpoint to use with the API).

Authentication V4

Version 4 of the Authentication endpoint is backwards compatible with all APIs that authenticate using version V3. If your API uses V3 to authenticate, you can also use the V4 endpoint, which only requires one certificate and does not require signing and encryption.

Please refer to the Authentication section in each API to determine which version of the Authentication endpoint (V1, V2, V3, or V4) you need to use.


Certificate setup

Click on the Credentials & Certificates tab on the Portal dashboard to upload your certificates and download Citi’s certificates to install on your server.

Authentication with APIs using versions 1, 2, or 3 of the Authentication endpoint require three certificates. Authentication with version 4 of the endpoint only requires one certificate.

Your certificates

You will need to upload the following certificates to make a request to Citi’s APIs that use version 1, 2, or 3 of the authentication endpoint:

CertificateTypeEncryptionPurpose
Client TLS CertificatePublic CertificateTLS v1.2The client TLS Certificate for mutual Authentication and Authorization of the encrypted connection between your application and Citi APIs.
Client Encryption CertificateClient TLS CertificateAES-256-GCMThe client encryption certificate used by Citi to decrypt your request payload ciphertext.
Client Signing CertificatePublic CertificateJOSEThe signing certificate that Citi will use to verify your request payload.

APIs that use V4 of the authentication endpoint only require an SSL certificate.

For your certificates, note that:

  • The Commercial Cards APIs do not require a signing certificate.
  • Your signing certificate can also be used for encryption. You can optionally add a separate certificate for encryption.
  • Authentication V4 only requires an SSL certificate.
  • Wildcard certificates are not allowed by Citi Information Security policy.

Citi certificates

You will need to download the following certificates from the Credentials & Certificates tab on your dashboard for APIs that use version 1, 2, or 3 of the authentication endpoint:

CertificateTypeEncryptionPurpose
Client TLS CertificatePublic CertificateTLS v1.2The Citi TLS Certificate for mutual Authentication and Authorization of the encrypted connection between your application and Citi APIs.
Client Encryption CertificatePublic CertificateAES-256-GCMThe Citi encryption certificate that you will use to decrypt the response payload ciphertext.
Client Signing CertificatePublic CertificateJOSE-JWTThe signing certificate that you will use to verify Citi’s response payload.

APIs that use V4 of the authentication endpoint only require an SSL certificate.

Although you do not need to set up the sandbox certificates to test the API behavior based on a preset default set up, testing of the APIs with your own customized settings and accounts can only be done once the sandbox certificates are valid and deployed.

Citi representatives will never ask for your private keys. For security, follow your organization’s policies on sharing private keys.


Certificate requirements

Citi has entered into an arrangement with DigiCert, a leading digital certificate authority, to help make digital certificates available to our customers in select countries*. Using this option ensures that your certificate meets all of our requirements. You can request a DigiCert certificate through the Portal:

  • Click the Credentials & Certificates tab of your Portal dashboard.
  • Navigate to Add Certificate.
  • Select I want Citi to help me obtain an SSL or Signing Certificate.

*Countries where DigiCert certificates are available include: Argentina, Australia, Bangladesh, Brazil, Cameroon, Canada, China, Colombia, Congo (DRC), Costa Rica, Czech Republic, Ecuador, El Salvador, France, Gabon, Germany, Ghana, Guatemala, Haiti, Honduras, Hong Kong, Hungary, India, Indonesia, Ireland, Ivory Coast, Japan, Jordan, Kazakhstan, Kenya, Kuwait, Macau, Morocco, New Zealand, Nigeria, Philippines, Poland, Romania, Russia, Saudi Arabia, Senegal, Singapore, Slovakia, South Africa, Sri Lanka, Sweden, Switzerland, Taiwan, Tanzania, Thailand, Trinidad & Tobago, Turkey, UAE, Uganda, Ukraine, United Kingdom, United States, Uruguay, Vietnam, Zambia.

Minimum Certificate Requirements

  • Certificates must be issued by a Certificate Authority (CA) that is a member of the Certificate and Browser forum. You can find a list of recognized authorities here.
  • X509 certificates with file formats of *.cer or *.pem are accepted for signing and encryption. The base64-encoded certificate file must be embedded with all intermediate and root certificates.
  • Certificates should use a Certificate Name (CN) value in the Subject field. It is recommended that production certificates be valid for at least six months from the date they are uploaded. Certificates for test environments can expire in as little as one day.
  • Certificates for both testing and production environments must be either Organization Validated (OV) or Extended Validation (EV). EV Certificates provide more trust and security than OV Certificates.
  • OV Certificates are verified for legitimate business information. As an example: Certificate Name CN = www.domain.com, Organization O = Domain Services ltd., Organizational Unit OU = Treasury IT, Location L = San Diego, State S = California, Country C = US.
  • In the Sandbox environment, the minimum certificate validity is 7 days up to a maximum of 26 months.
  • In the Production environment, the minimum certificate validity is 3 months up to a maximum of 26 months.
  • The Client SSL Certificate must include Extended Key Usage containing either both Server and Client Authentication or Client Authentication only on Leaf node level. Learn more here. As an example: Server Authentication (1.3.6.1.5.5.7.3.1), Client Authentication (1.3.6.1.5.5.7.3.2).

Not Permitted

  • Domain Validated (DV) Certificates are not acceptable since the issuing CA checks only the domain registry and not the legal entity/organizational unit.
  • Certificates including Server Authentication Extended Key Usage only are not acceptable for Client SSL certificate type.

You are expected to monitor the expiration of your certificates and renew the keys appropriately. Citi monitors the renewal and upgrade dates of certificates downloaded from Citi. We will contact you when these certificates must be renewed or upgraded.


Request an access token

Citi uses mutual, two-way authentication and OAuth 2.0 standard to authenticate and authorize API requests from your application.

Before requesting an access token, ensure that you have created an account on the developer portal, retrieved your Client ID and Secret, uploaded and downloaded your certificates, and confirmed with your Citi Representative that your environment is set up correctly.

To receive an Access Token from Citi, you need to send an API request to our Authentication endpoint:

1

Encode your credentials

Using a standard Base64 tool, encode your Client ID and Client Secret.

2

Create request header

Include the encoded and formatted credentials in the request header.

3

Create request body

Refer to the API Reference for the specific API and include the required parameters in the request body.

4

Encrypt the payload

Sign and encrypt the payload before sending it in the request message. Not applicable for APIs using Authentication V4.

Citi will verify and decrypt your request and authenticate your credentials. An Access Token will then be returned to you in the response.

All API requests must be made over HTTPS. Calls made over HTTP and API requests without authentication will fail.

Token length may vary based on the claims included and cryptographic characteristics, and may change over time as part of normal product evolution. As is standard practice among major identity providers, we reserve the right to modify token size without prior notice.

Access token expiration

The Access Token is only valid for a limited time and currently is set to 1800 seconds. The validity time for the token is returned to you in the response expires_in field. When the access token has expired, any API request that your application makes will return the HTTP status code 401 Unauthorized.

Token expiry

Citi does not provide a Refresh token.

When your Access Token has expired, you have two options to determine when you will request a new Access Token:

  1. Read the expires_in field in the returned OAuth response and when the Access Token has expired, request a new Access Token.
  2. Only renew your Access Token when you receive a 401 Unauthorized error back from Citi.

Encrypting and signing API requests

Most Citi API requests are encrypted and signed using asymmetric Public Key Infrastructure (PKI) cryptography before being transmitted.

APIs that authenticate using V4 of the authentication endpoint do not require signing encryption.

The following steps refer to the example code snippets below.

Encryption and signing

1

Initialize variables for signing and encryption

  1. Pass the signing certificate alias that you received from the Certificate Authority in the signKeyAlias field.
  2. Include your sign certificate password you received from the Certificate Authority in the signKeyPassword field.
  3. Pass the path to your local certificate in FileInputStream.
  4. Include the path to the Citi encryption certificate saved locally onto your server.
2

Sign and encrypt the plain text

Example: { "oAuthToken": { "grantType": "client_credentials", "scope": "/authenticationservices/v1" } };

3

Initialize variables to invoke Citi APIs

  1. Pass the SSL certificate location in the keystore.
  2. Include your SSL password in the KeyStorePassword field.
  3. Include the Citi endpoint that you would like to invoke.
  4. Include your Client ID and Client Secret into the Authorization variable.
4

Make an API call

Pass the initialized variables and call the Citi API.

Decryption

1

Initialize variables for decryption and signature verification

  1. Use your decrypt certificate alias in the decryptKeyAlias field. You should receive your decrypt certificate alias from your Certificate Authority.
  2. If you do not have a separate decrypt certificate, you can use your signing certificate instead.
  3. Include your decrypt certificate password in the decryptKeyPassword field. Your decrypt certificate password should be provided by your Certificate Authority.
  4. In the FileInputStream, add the decrypt keystore path where you have copied and stored your decrypt certificate.
  5. Include the Citi Signature verification certificate path that you have saved locally.
2

Decrypt and verify signature

  1. Pass the encrypted response by using the code to decrypt and verify the signature.
  2. You will receive the plain response in the verified variable.

Signing code snippet

JsonWebSignature jwsignature = new JsonWebSignature();
jwsignature.setPayload(plainText);
jwsignature.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
jwsignature.setKey(signPrivateKey);
String signed = jwsignature.getCompactSerialization();
JsonWebEncryption jwe = new JsonWebEncryption();
jwe.setPlaintext(signed);
jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.RSA_OAEP_256);
jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_256_GCM);
jwe.setKey(encryptPublicCert.getPublicKey());
String encryptedPayload = jwe.getCompactSerialization();

API call code snippet

String responseBody = null;
try {
ResponseEntity responseEntity = restTemplate.exchange(apimUri,
HttpMethod.POST, requestEntity, String.class);
responseBody = responseEntity.getBody();
} catch (HttpStatusCodeException hsce) {
responseBody = hsce.getResponseBodyAsString();
}

Encryption code snippet

String signKeyAlias = "your_signing_certificate_alias";
String signKeyPassword = "your_signing_certificate_password";
KeyStore signKeyStore = KeyStore.getInstance("PKCS12");
signKeyStore.load(new FileInputStream("your_sign_keystore_path"),
signKeyPassword.toCharArray());
PrivateKey signPrivateKey = (PrivateKey) signKeyStore.getKey(signKeyAlias,
signKeyPassword.toCharArray());
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate encryptPublicCert = (X509Certificate)
certFactory.generateCertificate(new FileInputStream("path_to_your_citi_encryption_certificate"));
String plainText = "{ \"oAuthToken\": { \"grantType\": \"client_credentials\", \"scope\": \"/authenticationservices/v1\" } }";

Initialization code snippet

InputStream keyStore = new FileInputStream("");
String keyStorePassword = "";
String apimUri = "";
String requestBody = encryptedPayload;
HttpHeaders requestHeaders = new HttpHeaders();
String authorization = "" + ":" + "";
requestHeaders.add("Authorization", "Basic " + new
String(Base64.getEncoder().encode(authorization.getBytes())));
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
KeyStore clientStore = KeyStore.getInstance("PKCS12");
clientStore.load(keyStore, keyStorePassword.toCharArray());
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientStore, keyStorePassword.toCharArray());
KeyManager[] kms = kmf.getKeyManagers();
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(kms, null, new SecureRandom());
SSLConnectionSocketFactory sslConnectionSocketFactory = new
SSLConnectionSocketFactory(sslContext);
HttpClientBuilder httpClientBuilder = HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.setProxy(new HttpHost(proxyAddress, Integer.valueOf(proxyPort), "http"));
HttpComponentsClientHttpRequestFactory requestFactory = new
HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClientBuilder.build());
RestTemplate restTemplate = new RestTemplate(requestFactory);
HttpEntity requestEntity = new HttpEntity<>(requestBody, requestHeaders);