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

# Token Replacement in Request

> Replace card tokens with real card data and relay the request to a third-party API.

<Card title="Token Replacement Guide" icon="book" href="/use-tokens/token-replacement-in-request">
  Replace tokens with card data in API requests
</Card>

This is PCI Booking's core proxy feature. Instead of processing payments through PCI Booking's gateway integrations, you send the exact API request your third-party system expects, with token placeholders where card data should go. PCI Booking swaps in the real card data and forwards the request transparently, so the third party receives a normal API call with real card details while you never handle sensitive data.

## Error Responses

| Code  | HTTP Status | Condition                                   |
| ----- | ----------- | ------------------------------------------- |
| -125  | 400         | httpMethod not POST/GET/PUT/PATCH/DELETE    |
| -160  | 404         | Card not found                              |
| -150  | 500         | Card retrieval failed                       |
| -125  | 400         | Profile name provided but profile not found |
| -125  | 400         | Content replacement failed                  |
| -125  | 400         | Empty content body                          |
| -125  | 400         | Missing Content-Type header                 |
| -125  | 400         | Target URI invalid                          |
| -1003 | 401         | User not owner and not associated           |

## Parameter Constraints

* **cardToken** must contain a valid card URI with a 32-hex token.
* **targetUri** is required.
* **httpMethod** defaults to POST. Accepted values: POST, GET, PUT, PATCH, DELETE.
* **postResponseAction** accepts `ClearCVV` or `DeleteToken`.

<Note>
  All URLs must be HTTPS. URL-encode all query string components.
</Note>

## 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="cardToken" type="string" required>
  The token URI identifying the card in PCI Booking.
</ParamField>

<ParamField query="targetURI" type="string" required>
  The HTTPS URL of the third party to relay the request to.
</ParamField>

<ParamField query="httpMethod" type="string" required>
  The HTTP method to use when calling the target URI. One of: `POST`, `GET`, `PUT`, `PATCH`, `DELETE`.
</ParamField>

<ParamField query="profileName" type="string">
  The ID of a [target profile](/account-setup/target-profiles) configured for this request. If omitted, PCI Booking uses [placeholder-based replacement](/use-tokens/token-replacement-in-request#how-it-works) instead.
</ParamField>

<ParamField query="contentParam" type="string">
  For placeholder-based replacement: the key containing card data in form-data or query string. Ignored if `profileName` is provided. If omitted, PCI Booking searches the request body for [placeholders](/use-tokens/token-replacement-in-request#supported-content-types).
</ParamField>

<ParamField query="postResponseAction" type="string">
  Action to perform after a successful relay. `ClearCVV` clears the CVV from the token. `DeleteToken` deletes the token entirely. If omitted, no action is taken.
</ParamField>

<ParamField query="timeout" type="int">
  Seconds to wait for the third-party response before timing out.
</ParamField>

### Headers

<ParamField header="Content-Encoding" type="string">
  Compression format: `gzip` or `deflate`. Omit if no compression is needed.
</ParamField>

### Request Body

The request body is relayed to the third party as-is, with token placeholders replaced by real card data. Structure it as required by the third party's API.

## Request Example

Send a JSON payment request to a third-party API, with PCI Booking replacing the card placeholders with real data before forwarding:

<Tabs>
  <Tab title="curl">
    ```bash theme={null}
    curl -X POST "https://service.pcibooking.net/api/payments/paycard/relay?cardToken=https%3A%2F%2Fservice.pcibooking.net%2Fapi%2Fpayments%2Fpaycard%2Ftok_abc123&targetURI=https%3A%2F%2Fapi.thirdparty.com%2Fv1%2Fpayments&httpMethod=POST" \
      -H "Authorization: APIKEY your-api-key" \
      -H "Content-Type: application/json" \
      -d '{
        "amount": 250.00,
        "currency": "USD",
        "card": {
          "number": "{{CardNo}}",
          "expMonth": "{{ExpMonth}}",
          "expYear": "{{ExpYear}}",
          "cvv": "{{Cvv}}",
          "holderName": "{{NameOnCard}}"
        },
        "reference": "order-98765"
      }'
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    const params = new URLSearchParams({
      cardToken: "https://service.pcibooking.net/api/payments/paycard/tok_abc123",
      targetURI: "https://api.thirdparty.com/v1/payments",
      httpMethod: "POST"
    });

    const response = await fetch(
      `https://service.pcibooking.net/api/payments/paycard/relay?${params}`,
      {
        method: "POST",
        headers: {
          "Authorization": "APIKEY your-api-key",
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          amount: 250.00,
          currency: "USD",
          card: {
            number: "{{CardNo}}",
            expMonth: "{{ExpMonth}}",
            expYear: "{{ExpYear}}",
            cvv: "{{Cvv}}",
            holderName: "{{NameOnCard}}"
          },
          reference: "order-98765"
        })
      }
    );

    const data = await response.text();
    console.log(data);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests

    response = requests.post(
        "https://service.pcibooking.net/api/payments/paycard/relay",
        params={
            "cardToken": "https://service.pcibooking.net/api/payments/paycard/tok_abc123",
            "targetURI": "https://api.thirdparty.com/v1/payments",
            "httpMethod": "POST"
        },
        headers={
            "Authorization": "APIKEY your-api-key",
            "Content-Type": "application/json"
        },
        json={
            "amount": 250.00,
            "currency": "USD",
            "card": {
                "number": "{{CardNo}}",
                "expMonth": "{{ExpMonth}}",
                "expYear": "{{ExpYear}}",
                "cvv": "{{Cvv}}",
                "holderName": "{{NameOnCard}}"
            },
            "reference": "order-98765"
        }
    )

    print(response.text)
    ```
  </Tab>
</Tabs>

PCI Booking replaces the `{{CardNo}}`, `{{ExpMonth}}`, `{{ExpYear}}`, `{{Cvv}}`, and `{{NameOnCard}}` placeholders with the actual card data from the token before forwarding the request to `api.thirdparty.com`.

To use a target profile (pre-configured replacement rules) instead of inline placeholders:

<Tabs>
  <Tab title="curl">
    ```bash theme={null}
    curl -X POST "https://service.pcibooking.net/api/payments/paycard/relay?cardToken=https%3A%2F%2Fservice.pcibooking.net%2Fapi%2Fpayments%2Fpaycard%2Ftok_abc123&targetURI=https%3A%2F%2Fapi.thirdparty.com%2Fv1%2Fpayments&httpMethod=POST&profileName=my-thirdparty-profile" \
      -H "Authorization: APIKEY your-api-key" \
      -H "Content-Type: application/json" \
      -d '{
        "amount": 250.00,
        "currency": "USD",
        "reference": "order-98765"
      }'
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    const params = new URLSearchParams({
      cardToken: "https://service.pcibooking.net/api/payments/paycard/tok_abc123",
      targetURI: "https://api.thirdparty.com/v1/payments",
      httpMethod: "POST",
      profileName: "my-thirdparty-profile"
    });

    const response = await fetch(
      `https://service.pcibooking.net/api/payments/paycard/relay?${params}`,
      {
        method: "POST",
        headers: {
          "Authorization": "APIKEY your-api-key",
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          amount: 250.00,
          currency: "USD",
          reference: "order-98765"
        })
      }
    );

    const data = await response.text();
    console.log(data);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests

    response = requests.post(
        "https://service.pcibooking.net/api/payments/paycard/relay",
        params={
            "cardToken": "https://service.pcibooking.net/api/payments/paycard/tok_abc123",
            "targetURI": "https://api.thirdparty.com/v1/payments",
            "httpMethod": "POST",
            "profileName": "my-thirdparty-profile"
        },
        headers={
            "Authorization": "APIKEY your-api-key",
            "Content-Type": "application/json"
        },
        json={
            "amount": 250.00,
            "currency": "USD",
            "reference": "order-98765"
        }
    )

    print(response.text)
    ```
  </Tab>
</Tabs>

## Response

**200** - The third-party response, relayed back as-is.

<Info>
  Consider adding business logic based on the [CVV retention policy status](/capture-cards/cvv-retention-policy) after a token replacement request.
</Info>

<ResponseExample>
  ```text 200 theme={null}
  The third-party response is returned as-is. The format and content depend entirely on the destination API.
  ```

  ```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
  }
  ```

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

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