> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/classic-tokenization/use-cases/synchronize-tokens-using-batch-files/batch-file-structure.md).

# Batch file structure

This page defines the batch file format that the issuer backend provides for batch updates.

### Batch file structure <a href="#batch-file-structure" id="batch-file-structure"></a>

The batch file has the following structure:

| NAME      | TYPE   | M/O/C | DESCRIPTION                                                                                                                                                                                                                                                                                                                                              |
| --------- | ------ | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| header    | Object | M     | The header describing the batch update request.                                                                                                                                                                                                                                                                                                          |
| records   | Array  | M     | The array containing the records. Each record corresponds to an operation.                                                                                                                                                                                                                                                                               |
| signature | String | M     | This field represents a detached JSON Web Signature (JWS). The signature must be created with the issuer private key. During D1 onboarding, the issuer shares the corresponding public key. For details, see [JWS](https://thales-dis-dbp.stoplight.io/docs/digital-payment/branches/api-releases-v2.9.0/oeju7u3guavui-batch-file-definition#signature). |

#### Header <a href="#header" id="header"></a>

The header has the following structure:

| NAME      | TYPE   | SIZE | M/O/C | DESCRIPTION                                                                                              |
| --------- | ------ | ---- | ----- | -------------------------------------------------------------------------------------------------------- |
| batchId   | String | 48   | M     | The identifier of the batch file as specified in the file name.                                          |
| seqNumber | String | 48   | M     | The sequence number of the batch file as specified in the file name.                                     |
| issuerId  | String | 48   | M     | The identifier of the issuer.                                                                            |
| operation | String | 48   | M     | Identifies the operation that will be performed with the input file. Value: `VIRTUAL_CARD_REGISTRATION`. |

#### Records <a href="#records" id="records"></a>

A record has the following structure:

| NAME                           | TYPE   | SIZE | M/O/C | DESCRIPTION                                    |
| ------------------------------ | ------ | ---- | ----- | ---------------------------------------------- |
| rowId                          | int    | -    | M     | The incremental row identifier.                |
| virtualCardRegistrationRequest | Object | -    | M     | The virtual card registration request payload. |

**virtualCardRegistrationRequest**

| NAME | TYPE                | SIZE | M/O/C | DESCRIPTION                                   |
| ---- | ------------------- | ---- | ----- | --------------------------------------------- |
| card | Object of type Card | N/A  | M     | An object containing the encrypted card data. |

Where the *card* has the following structure:

| NAME          | TYPE   | SIZE   | M/O/C | DESCRIPTION                                          |
| ------------- | ------ | ------ | ----- | ---------------------------------------------------- |
| id            | String | 1...48 | M     | The unique identifier assigned by the issuer.        |
| encryptedData | String | -      | M     | PKCS#7 payload encrypted with the Thales public key. |
| scheme        | String | -      | M     | Values: `VISA` or `MASTERCARD`.                      |

The content encryption algorithm is `AES256/CBC/PKCS7Padding`.

The supported key encryption algorithm for an RSA public key (2048-bit) is `RSA/OAEPWithSHA256AndMGF1Padding`.

For details, see [Data encryption and security](/classic-tokenization/get-started/api-basics/data-encryption-and-security.md).

The structure of the deciphered payload is as follows:

| NAME | TYPE   | SIZE     | M/O/C | DESCRIPTION                                                       |
| ---- | ------ | -------- | ----- | ----------------------------------------------------------------- |
| fpan | String | Up to 20 | M     | FPAN of the funding card. Example: `{"fpan":"6789451266992345"}`. |

### Signature <a href="#signature" id="signature"></a>

The signature object uses the JWS scheme as specified by [RFC 7515](https://datatracker.ietf.org/doc/html/rfc7515).

During D1 onboarding, the issuer must share the public key.

#### Process <a href="#process" id="process"></a>

1. Remove carriage returns and whitespace from the payload.
2. Encode the payload using `UTF-8`.
3. Initialize a signing object with the encoded data.
4. Set the protected header:
   1. `alg = "PS256"`
   2. `kid = "key identifier"`
5. Use the private key to sign the data and produce a JWS object.
6. Split the JWS string into parts using `.` as the separator.
7. Create the detached signature by combining the first and third parts with `..`.
8. Return the detached signature.

Example (Node.js):

```javascript
const jose = require("jose");
const { pem2jwk } = require("pem-jwk");

async function generateJWS() {
        const issuerSignPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
................................................................
................................................................
................................................................
-----END RSA PRIVATE KEY-----`;

    // Convert the PEM private key to JWK format
    const privateKeyJWK = pem2jwk(issuerSignPrivateKey);

    // Import the JWK into a key object
    const privateKey = await jose.importJWK(privateKeyJWK);

    // Create the payload to sign (as an object)
    const input = {"header": {...},"records": [...]};
    // Stringify and remove whitespace
    const payload = JSON.stringify(input).replace(/\s+|\r?\n|\r|\n|\t/g, "");
    const encode = new TextEncoder().encode(payload);

    // Sign the payload with the private key
    const jws = await new jose.CompactSign(encode)
        .setProtectedHeader({ alg: "PS256", kid: "KID_VALUE" })
        .sign(privateKey);

    // Split the JWS to create the signature
    const signParts = jws.split(".");
    const signature = signParts[0] + ".." + signParts[2];

    console.log("Signature:", signature);
}

// Call the function
generateJWS();
```

**JWS composition**

The following format shows the representation of a JWS object:

`Base64URL(UTF-8(JWS header)) || '.' || Base64URL(JWS payload) || '.' || Base64URL(JWS signature)`

As the detached signature is used, the JWS Payload is replaced by an empty string:

`Base64URL(UTF-8(JWS header)) || '..' || Base64URL(JWS signature)`

**JWS header**

The header contains the following metadata:

| NAME | TYPE   | SIZE | REQUIRED/OPTIONAL/CONDITIONAL | DESCRIPTION                                               |
| ---- | ------ | ---- | ----------------------------- | --------------------------------------------------------- |
| alg  | Enum   | n/a  | Required                      | Algorithm used to sign the JWS payload. Value is `PS256`. |
| kid  | String | 64   | Required                      | Key identifier of the key used to sign the JWS payload.   |

**JWS payload**

The payload to sign is a JSON object with the `header` and `records` attributes. It uses `UTF-8` encoding and contains no carriage returns or whitespace. Example: `{header:{...},records:[...]}`

### Batch file example <a href="#batch-file-example" id="batch-file-example"></a>

```json
{
    "header": {
        "batchId": "0000000000001111111111FF",
        "seqNumber": "005",
        "operation": "VIRTUAL_CARD_REGISTRATION",
        "issuerId": "BANK_ABC"},
    "records": [
            {
            "rowId": 0,
            "virtualCardRegistrationRequest": {
                "card":{
                    "id":"FWSPMC000000000fcb2f4136b2f4136a0532d2f4136a0532",
                    "encryptedData":"KDlTthhZTGufMY…….xPSUrfmqCHXaI9wOGY=",
                    "scheme":"MASTERCARD"}
                }
            },
            {
            "rowId": 1,
            "virtualCardRegistrationRequest": {
                "card":{
                    "id":"FWSPMC000000000fcb2f4136b2f4136a0532d2f4136a0532",
                    "encryptedData":"KDlTthhZTGufMY…….xPSUrfmqCHXaI9wOGY=",
                    "scheme":"MASTERCARD"}
                }
            }
    ],
    "signature": "AxY8DctDa….GlsbGljb3RoZQ="
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.payments.thalescloud.io/classic-tokenization/use-cases/synchronize-tokens-using-batch-files/batch-file-structure.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
