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

# Reserve Virtual Accounts

POST https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts
Content-Type: application/json

The virtual account creation is a 2-step process (using the reservation and activation services), you can use POST and PUT endpoints one after another.  Contact your citi representative for the number of accounts you can request for reservation per API.   Use POST verb for Reservation action          - The API support XML and JSON formats.  - The reservation/activation functionality is identified based on the request payload (`action`).  - You specify values for input parameters in the body of your XML/JSON document.  - You encrypt the payload, place it in your request and send it with your application.\<font size='2'>Content-Type: Supports application/xml and application/json. Authorization: The OAuth Token prefixed with bearer and a space in between. Allowed characters: A-Z, a-z, 0-9, Space Allowed punctuation marks: ' ( ) \* - , . / : ; \_ &  \$ # @ \[ ]

Reference: https://citi-demo.ferndocs.com/enterprises/api-reference/account-services/receivable-services/virtual-accounts-wallet/virtual-account-reservation

## Authentication

- `Authorization` header (bearer token, required) — All CitiConnect APIs use the oAuth2 authentication scheme, which requires a bearer token to authenticate your API call. The Token URL includes the version of authentication used by this API. See the Citi Authentication API reference for information on requesting a token.

## Servers

- `https://tts.sandbox.apib2b.citi.com/citiconnect/sb` (sandbox URL , default)
- `https://b2b.tts.icgservices.citi.com/citiconnect/prod` (production gateway URL)

## Request

### Query parameters

- `client_id` (string, required) — Unique reference shared during CitiConnect API onboarding (`client_id` used during OAuth token generation).

### Headers

- `Idempotency-Id` (string, required) — Your unique identification for a POST request - Maximum length is 128. - CitiConnect API responds with an error (HTTP status 4XX) if your POST request idempotency identification value is a duplicate across a recent history of idempotency identifications in Citi's database- If you don't receive any response (HTTP status 2XX, 4XX or 5XX) from Citi to your POST request and you wish to retry, re-initiate your request with the same idempotency identification to prevent an accidental duplicate payment.

### Body (application/json)

This endpoint expects a Virtual-Account-Reservation-Request.

- `action` (enum, required) — Action is a request type. - Choose the action value as ''RESERVATION'', if you want to reserve virtual accounts for the previous virtual header account.
  - Allowed values: `RESERVATION`
- `header_account` (Header-Account, optional)
- `number_of_accounts_required` (integer, optional) — Required parameter only if the value of the `action` parameter is 'RESERVATION'. This parameter specifies the number of virtual accounts requested to be reserved. Minimum account that can be requested/supported under one API call is 1. Contact your Citi representative for the number of accounts you are allowed to request per API call.
- `purpose` (enum, optional) — Thsi parameter specifies the purpose for the creation of the virtual account. This is a required parameter for both the `action` parameters, 'RESERVATION' and 'ACTIVATION'. Allowed value is 'C'. - 'C' - Client's Customer
  - Allowed values: `C`

## Response

### 202

Accepted

- `request_id` (string, optional) — Auto-generated unique identification assigned for the request.
- `status` (string, optional) — Status of the request. Possible statuses are SUCCESS REJECTED PENDING
- `message` (string, optional) — Detailed response for the particular request.
- `action` (string, optional) — Action of the given request. - ''RESERVATION'' - ''ACTIVATION''.
- `branch_code` (string, optional) — Citi's bank code associated with given a header account number.
- `error_details` (list of Error-Detail, optional)
- `account` (list of Accounts, optional)

## Errors

### 400 Bad Request Error

Bad Request

- `ref_id` (string, optional) — Uniqiue reference ID for a particular request.
- `error_details` (list of Error-Detail, optional)
- `httpCode` (string, optional)
- `httpMessage` (string, optional)
- `moreInformation` (string, optional)
- `status` (string, optional)
- `message` (string, optional)

### 401 Unauthorized Error

Unauthorized

- `ref_id` (string, optional) — Uniqiue reference ID for a particular request.
- `error_details` (list of Error-Detail, optional)
- `httpCode` (string, optional)
- `httpMessage` (string, optional)
- `moreInformation` (string, optional)
- `status` (string, optional)
- `message` (string, optional)

### 403 Forbidden Error

Forbidden

- `ref_id` (string, optional) — Uniqiue reference ID for a particular request.
- `error_details` (list of Error-Detail, optional)
- `httpCode` (string, optional)
- `httpMessage` (string, optional)
- `moreInformation` (string, optional)
- `status` (string, optional)
- `message` (string, optional)

### 404 Not Found Error

Not Found

- `httpCode` (string, optional) — HTTP status code of this API.
- `httpMessage` (string, optional) — Short message about the issue.
- `moreInformation` (string, optional) — More information about the issue.

### 405 Method Not Allowed Error

Method Not Allowed

- `ref_id` (string, optional) — Uniqiue reference ID for a particular request.
- `error_details` (list of Error-Detail, optional)
- `httpCode` (string, optional)
- `httpMessage` (string, optional)
- `moreInformation` (string, optional)
- `status` (string, optional)
- `message` (string, optional)

### 409 Conflict Error

Conflict

- `ref_id` (string, optional) — Uniqiue reference ID for a particular request.
- `error_details` (list of Error-Detail, optional)
- `httpCode` (string, optional)
- `httpMessage` (string, optional)
- `moreInformation` (string, optional)
- `status` (string, optional)
- `message` (string, optional)

### 415 Unsupported Media Type Error

Unsupported Media Type

- `ref_id` (string, optional) — Uniqiue reference ID for a particular request.
- `error_details` (list of Error-Detail, optional)
- `httpCode` (string, optional)
- `httpMessage` (string, optional)
- `moreInformation` (string, optional)
- `status` (string, optional)
- `message` (string, optional)

### 429 Too Many Requests Error

Too Many Request

- `status` (string, optional) — HTTP status code of this API response.
- `message` (string, optional) — Short message about the issue.

### 500 Internal Server Error

Internal Server Error

- `ref_id` (string, optional) — Uniqiue reference ID for a particular request.
- `error_details` (list of Error-Detail, optional)
- `httpCode` (string, optional)
- `httpMessage` (string, optional)
- `moreInformation` (string, optional)
- `status` (string, optional)
- `message` (string, optional)

## Types

### Header-Account

- `account` (string, optional) — Required parameter if the value of the `action` parameter is 'RESERVATION' (or) 'ACTIVATION' (or) 'UPDATE'. Specifies the header account number assigned during the account opening.
- `branch_code` (string, optional) — Citi's bank code associated with given a header account number.

### Error-Detail

- `code` (string, optional) — Unique ID for the error code. Under GET method and callbacks, this parameter is a non-retrievable internal error code:CC00013.
- `issue` (string, optional) — More details about the issue.
- `action` (string, optional) — Corrective action to be taken to resolve above issue.

### Accounts

- `virtual_account` (string, optional) — Required parameter only if the value of the `action` parameter is set to 'ACTIVATION'.This parameter specifies the virtual account to be activated.
- `entity_id` (string, optional) — ID that was assigned specific to the entity being activated under this virtual account.

## Examples

### VAReservationExample (application/json)

**Request**

```json
{
  "action": "RESERVATION",
  "header_account": {
    "account": "0011224455",
    "branch_code": "930"
  },
  "number_of_accounts_required": 50,
  "purpose": "C"
}
```

**Response**

```json
{
  "request_id": "29b9c9d7-d4d9-48ce-8823-f9b3ee276b8f",
  "status": "ACCEPTED",
  "message": "Request accepted Successfully"
}
```

**SDK Code**

```python VAReservationExample (application/json)
import requests

url = "https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts"

payload = {
    "action": "RESERVATION",
    "header_account": {
        "account": "0011224455",
        "branch_code": "930"
    },
    "number_of_accounts_required": 50,
    "purpose": "C"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript VAReservationExample (application/json)
const url = 'https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"action":"RESERVATION","header_account":{"account":"0011224455","branch_code":"930"},"number_of_accounts_required":50,"purpose":"C"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go VAReservationExample (application/json)
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts"

	payload := strings.NewReader("{\n  \"action\": \"RESERVATION\",\n  \"header_account\": {\n    \"account\": \"0011224455\",\n    \"branch_code\": \"930\"\n  },\n  \"number_of_accounts_required\": 50,\n  \"purpose\": \"C\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	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 VAReservationExample (application/json)
require 'uri'
require 'net/http'

url = URI("https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"action\": \"RESERVATION\",\n  \"header_account\": {\n    \"account\": \"0011224455\",\n    \"branch_code\": \"930\"\n  },\n  \"number_of_accounts_required\": 50,\n  \"purpose\": \"C\"\n}"

response = http.request(request)
puts response.read_body
```

```java VAReservationExample (application/json)
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"action\": \"RESERVATION\",\n  \"header_account\": {\n    \"account\": \"0011224455\",\n    \"branch_code\": \"930\"\n  },\n  \"number_of_accounts_required\": 50,\n  \"purpose\": \"C\"\n}")
  .asString();
```

```php VAReservationExample (application/json)
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts', [
  'body' => '{
  "action": "RESERVATION",
  "header_account": {
    "account": "0011224455",
    "branch_code": "930"
  },
  "number_of_accounts_required": 50,
  "purpose": "C"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp VAReservationExample (application/json)
using RestSharp;

var client = new RestClient("https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"action\": \"RESERVATION\",\n  \"header_account\": {\n    \"account\": \"0011224455\",\n    \"branch_code\": \"930\"\n  },\n  \"number_of_accounts_required\": 50,\n  \"purpose\": \"C\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift VAReservationExample (application/json)
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "action": "RESERVATION",
  "header_account": [
    "account": "0011224455",
    "branch_code": "930"
  ],
  "number_of_accounts_required": 50,
  "purpose": "C"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts")! 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()
```

### VAReservationExample (application/xml)

**Request**

```json
{
  "action": "RESERVATION",
  "header_account": {
    "account": "0011224455",
    "branch_code": "930"
  },
  "number_of_accounts_required": 50,
  "purpose": "C"
}
```

**Response**

```json
{
  "request_id": "29b9c9d7-d4d9-48ce-8823-f9b3ee276b8f",
  "status": "ACCEPTED",
  "message": "Request accepted Successfully"
}
```

**SDK Code**

```python VAReservationExample (application/xml)
import requests

url = "https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts"

payload = {
    "action": "RESERVATION",
    "header_account": {
        "account": "0011224455",
        "branch_code": "930"
    },
    "number_of_accounts_required": 50,
    "purpose": "C"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript VAReservationExample (application/xml)
const url = 'https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"action":"RESERVATION","header_account":{"account":"0011224455","branch_code":"930"},"number_of_accounts_required":50,"purpose":"C"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go VAReservationExample (application/xml)
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts"

	payload := strings.NewReader("{\n  \"action\": \"RESERVATION\",\n  \"header_account\": {\n    \"account\": \"0011224455\",\n    \"branch_code\": \"930\"\n  },\n  \"number_of_accounts_required\": 50,\n  \"purpose\": \"C\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	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 VAReservationExample (application/xml)
require 'uri'
require 'net/http'

url = URI("https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"action\": \"RESERVATION\",\n  \"header_account\": {\n    \"account\": \"0011224455\",\n    \"branch_code\": \"930\"\n  },\n  \"number_of_accounts_required\": 50,\n  \"purpose\": \"C\"\n}"

response = http.request(request)
puts response.read_body
```

```java VAReservationExample (application/xml)
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"action\": \"RESERVATION\",\n  \"header_account\": {\n    \"account\": \"0011224455\",\n    \"branch_code\": \"930\"\n  },\n  \"number_of_accounts_required\": 50,\n  \"purpose\": \"C\"\n}")
  .asString();
```

```php VAReservationExample (application/xml)
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts', [
  'body' => '{
  "action": "RESERVATION",
  "header_account": {
    "account": "0011224455",
    "branch_code": "930"
  },
  "number_of_accounts_required": 50,
  "purpose": "C"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp VAReservationExample (application/xml)
using RestSharp;

var client = new RestClient("https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"action\": \"RESERVATION\",\n  \"header_account\": {\n    \"account\": \"0011224455\",\n    \"branch_code\": \"930\"\n  },\n  \"number_of_accounts_required\": 50,\n  \"purpose\": \"C\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift VAReservationExample (application/xml)
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "action": "RESERVATION",
  "header_account": [
    "account": "0011224455",
    "branch_code": "930"
  ],
  "number_of_accounts_required": 50,
  "purpose": "C"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://tts.sandbox.apib2b.citi.com/citiconnect/sb/receivablesservices/v2/virtualaccounts")! 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()
```