> ## Documentation Index
> Fetch the complete documentation index at: https://developers.pcibooking.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Tokenization in Response

> Route a request through PCI Booking to a third party. PCI Booking intercepts the response, tokenizes card data, masks the details, and returns the sanitized response.

<Card title="Tokenization on Response Guide" icon="book" href="/capture-cards/tokenization-on-response">
  Automatically tokenize cards from gateway responses
</Card>

PCI Booking forwards your request to the third party, tokenizes any card data found in the response (using your [target profile](/account-setup/target-profiles)), and returns the sanitized response with the following custom headers:

| Header                               | Description                                                                                                         |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `X-pciBooking-cardUri`               | Semicolon-separated list of token URIs for each card tokenized. The header name can be customized per profile.      |
| `X-pciBooking-Tokenization-Errors`   | Errors encountered during tokenization (e.g. invalid card number, missing fields). Present only if errors occurred. |
| `X-pciBooking-Tokenization-Warnings` | Warnings encountered during tokenization (e.g. expired card accepted). Present only if warnings occurred.           |

<Note>
  All URLs must be HTTPS and URL-encoded.
</Note>

## Error Responses

| Code  | HTTP Status | Condition                                  |
| ----- | ----------- | ------------------------------------------ |
| -125  | 400         | Empty relay message content (null body)    |
| -125  | 400         | Could not fetch a valid PCI Shield profile |
| -1003 | 401         | Missing `CanTokenize` permission           |

## Parameter Constraints

| Parameter   | Type    | Required | Constraints                                                                  |
| ----------- | ------- | -------- | ---------------------------------------------------------------------------- |
| targetURI   | string  | Yes      | Must be a valid HTTPS URL                                                    |
| profileName | string  | Yes      | Must match a configured target profile                                       |
| httpMethod  | string  | Yes      | Defaults to `POST`. Accepted values: `POST`, `GET`, `PUT`, `PATCH`, `DELETE` |
| timeout     | integer | No       | Number of seconds to wait for a response. Defaults to 0 (no timeout)         |
| Auth        | string  | Yes      | ApiKey, AccessToken, or SessionToken                                         |

## Parameters

### Authentication

<Warning>
  This is a browser-facing endpoint. Use one of the authentication methods below instead of the API key shown above.
</Warning>

<ParamField query="accessToken" type="string">
  Recommended. A long-lived token for browser-side calls. [How to generate](/getting-started/authentication#access-token).
</ParamField>

<ParamField query="sessionToken" type="string">
  Alternative. Valid for 5 minutes. [How to generate](/api-reference/general/start-temporary-session).
</ParamField>

If both are provided, the session token takes precedence.

### Query String

<ParamField query="profileName" type="string" required>
  The unique ID for the profile set up for the response you will receive for this request. You can set up as many profiles as you require. Read more about [target profiles](/account-setup/target-profiles).
</ParamField>

<ParamField query="targetURI" type="string" required>
  The URI of the third party to relay the request to. PCI Booking sends your request to this endpoint and intercepts the response.
</ParamField>

<ParamField query="httpMethod" type="string" required>
  The HTTP method that PCI Booking should use when calling the target URI. Possible values: `POST`, `GET`, `PUT`, `PATCH`, `DELETE`.
</ParamField>

<ParamField query="timeout" type="int">
  The number of seconds PCI Booking should wait for a response from the third party.
</ParamField>

<ParamField query="saveCVV" type="boolean" default="false">
  Whether to save the CVV in the database. `true`: save the CVV. `false`: discard the CVV.
</ParamField>

<ParamField query="ref" type="string">
  A reference value which can be used to query for this card token.
</ParamField>

<ParamField query="MerchantId" type="string">
  The user ID of the property to associate the token with. Found under "Property settings" in the user's site.
</ParamField>

<ParamField query="allowedUserId" type="string">
  The user ID of the PCI Booking customer (booker ID) to associate the token with. The PCI Booking customer must share their user ID with you.
</ParamField>

<ParamField query="eliminateCardDuplication" type="boolean" default="false">
  Controls whether PCI Booking checks if the card already exists as a token in your account.

  * **`true`**: PCI Booking looks up the card in your stored tokens. If a match is found, the existing token URI is returned instead of creating a new one. The response status will be `200` instead of `201`.
  * **`false`** (default): A new token is always created, even if the same card was previously stored.
</ParamField>

### Request Body

<Note>
  The request body and headers are passed through to the third party as-is. Include any body content and headers that the third party requires.
</Note>

<RequestExample>
  ```javascript Node.js theme={null}
  const params = new URLSearchParams({
    profileName: 'MyOTAProfile',
    targetURI: 'https://api.thirdparty.com/reservations/12345',
    httpMethod: 'POST',
    saveCVV: 'true',
    ref: 'booking-12345'
  });

  const response = await fetch(
    `https://service.pcibooking.net/api/payments/paycard/capture?${params}`,
    {
      method: 'POST',
      headers: {
        'Authorization': 'APIKEY your-api-key',
        'Content-Type': 'application/xml'
      },
      body: '<ReservationRequest><ID>12345</ID></ReservationRequest>'
    }
  );

  const tokenUri = response.headers.get('X-pciBooking-cardUri');
  console.log('Token URI:', tokenUri);

  const data = await response.text();
  console.log('Sanitized response:', data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://service.pcibooking.net/api/payments/paycard/capture',
      params={
          'profileName': 'MyOTAProfile',
          'targetURI': 'https://api.thirdparty.com/reservations/12345',
          'httpMethod': 'POST',
          'saveCVV': 'true',
          'ref': 'booking-12345'
      },
      headers={
          'Authorization': 'APIKEY your-api-key',
          'Content-Type': 'application/xml'
      },
      data='<ReservationRequest><ID>12345</ID></ReservationRequest>'
  )

  token_uri = response.headers.get('X-pciBooking-cardUri')
  print('Token URI:', token_uri)
  print('Sanitized response:', response.text)
  ```
</RequestExample>

## Response

**200** - The card already exists in your account (when `eliminateCardDuplication` is `true`). The response body contains the third-party response with card details masked. The existing token URI is returned in the `X-pciBooking-cardUri` header.

**201** - A new card was tokenized. The response body contains the third-party response with card details masked. The new token URI is returned in the `X-pciBooking-cardUri` header.

<Info>
  Remember to set the [CVV Retention Policy](/capture-cards/cvv-retention-policy) on the token.
</Info>

<ResponseExample>
  ```text 201 theme={null}
  The third-party response body is returned with card details replaced by token placeholders.
  The X-pciBooking-cardUri header contains the new token URI.
  ```

  ```json Invalid profile 400 theme={null}
  {
      "code": -125,
      "message": "Bad input data",
      "moreInfo": "Couldn't fetch a valid pciShield profile:: wsc",
      "errorList": null
  }
  ```

  ```json Invalid target URI 400 theme={null}
  {
      "code": -125,
      "message": "Bad input data",
      "moreInfo": "Invalid target Uri::",
      "errorList": null
  }
  ```

  ```json 401 theme={null}
  {
      "code": -1003,
      "message": "Not authorized to access this resource",
      "moreInfo": "Bad or missing authorization data, expected Temp Session or One-Time Accesss Token",
      "errorList": null
  }
  ```
</ResponseExample>
