> This page is for Enterprise.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://citi-demo.ferndocs.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://citi-demo.ferndocs.com/_mcp/server.

# Authentication Guide

> **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](https://knowledge.digicert.com/alerts/sunsetting-client-authentication-eku-from-digicert-public-tls-certificates).

> **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.

#### Create an account

[Create an account](https://developer.citi.com/apis/signup) on the Developer Portal. Skip this step if you're already signed up and logged in.

#### 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](https://developer.citi.com/apim/go/marketplace/) to see what APIs are available.

#### 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.

#### Get your credentials

Retrieve your Client ID and Client Secret from the [Credentials & Certificates tab of your dashboard](https://developer.citi.com/apim/go/home).

#### Set up certificates

Set up your certificates on the [Credentials & Certificates tab of your dashboard](https://developer.citi.com/apim/go/home).

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

#### Testing confirmation

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

#### Production confirmation

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

> **Info**
>
> If you do not know who your Citi representative is, email [devsupport@citi.com](mailto:devsupport@citi.com).

---

### Creating an account

> **Note**
>
> 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:

#### Complete registration form

Complete and submit the [sign up form](https://developer.citi.com/apis/signup).

#### Validate email

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

#### Complete sign in

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

> **Warning**
>
> Registration is complete only after the first login. If you experience issues completing registration, please contact [developer support](mailto:devsupport@citi.com).

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](https://developer.citi.com/apim/go/home). Citi will use these credentials to authenticate requests.

> **Success**
>
> **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](https://developer.citi.com/apim/go/home) 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.

> **Info**
>
> 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](https://developer.citi.com/apim/go/home) 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:

| Certificate                   | Type                   | Encryption  | Purpose                                                                                                                                    |
| ----------------------------- | ---------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Client TLS Certificate        | Public Certificate     | TLS v1.2    | The client TLS Certificate for mutual Authentication and Authorization of the encrypted connection between your application and Citi APIs. |
| Client Encryption Certificate | Client TLS Certificate | AES-256-GCM | The client encryption certificate used by Citi to decrypt your request payload ciphertext.                                                 |
| Client Signing Certificate    | Public Certificate     | JOSE        | The 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](https://developer.citi.com/apim/go/home) tab on your dashboard for APIs that use version 1, 2, or 3 of the authentication endpoint:

| Certificate                   | Type               | Encryption  | Purpose                                                                                                                                  |
| ----------------------------- | ------------------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Client TLS Certificate        | Public Certificate | TLS v1.2    | The Citi TLS Certificate for mutual Authentication and Authorization of the encrypted connection between your application and Citi APIs. |
| Client Encryption Certificate | Public Certificate | AES-256-GCM | The Citi encryption certificate that you will use to decrypt the response payload ciphertext.                                            |
| Client Signing Certificate    | Public Certificate | JOSE-JWT    | The 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.

> **Note**
>
> 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.

> **Info**
>
> Citi representatives will never ask for your private keys. For security, follow your organization's policies on sharing private keys.

---

### Certificate requirements

> **Tip**
>
> 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](https://developer.citi.com/apim/go/home) 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](https://cabforum.org/members/).
* 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](http://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.](https://knowledge.digicert.com/alerts/sunsetting-client-authentication-eku-from-digicert-public-tls-certificates) 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.

> **Info**
>
> 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:

#### Encode your credentials

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

#### Create request header

Include the encoded and formatted credentials in the request header.

#### Create request body

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

#### 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.

> **Info**
>
> 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

#### 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.

#### Sign and encrypt the plain text

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

#### 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.

#### Make an API call

Pass the initialized variables and call the Citi API.

#### Decryption

#### 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.

#### 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**

```java
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**

```java
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**

```java
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**

```java
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);
```