> This page is for Unified.

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

# Making a Passthrough Request

> How to send raw HTTP requests to a third-party integration's API through Merge, using the stored Linked Account credentials.

> **Info**
>
> This feature is only available to customers on our **Professional** or **Enterprise** plans. View the [Merge Plans](https://www.merge.dev/pricing) to learn more.

---

## API endpoint

Send POST requests to the URL below with the required body parameters to create a Passthrough Requests.

```
https://api.merge.dev/api/{CATEGORY}/passthrough
```

Replace `CATEGORY` in the URL with `hris`, `ats`, `accounting`, `ticketing`, `crm`, `mktg`, or `filestorage` depending on the relevant category you're making an API request to.

---

## Body Parameters

Reference the integration's API documentation to accurately fill out the body parameters for the specific Passthrough Request you're looking to make.

### Schema (`DataPassthroughRequest`)

```yaml
components:
  schemas:
    MethodEnum:
      type: string
      enum:
        - GET
        - OPTIONS
        - HEAD
        - POST
        - PUT
        - PATCH
        - DELETE
      title: MethodEnum
    EncodingEnum:
      type: string
      enum:
        - RAW
        - BASE64
        - GZIP_BASE64
      title: EncodingEnum
    MultipartFormFieldRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          description: The name of the form field
        data:
          type: string
          minLength: 1
          description: The data for the form field.
        encoding:
          oneOf:
            - $ref: '#/components/schemas/EncodingEnum'
            - type: 'null'
          default: RAW
          description: >-
            The encoding of the value of `data`. Defaults to `RAW` if not
            defined.
        file_name:
          type:
            - string
            - 'null'
          minLength: 1
          description: The file name of the form field, if the field is for a file.
        content_type:
          type:
            - string
            - 'null'
          minLength: 1
          description: The MIME type of the file, if the field is for a file.
      required:
        - name
        - data
      description: >-
        # The MultipartFormField Object

        ### Description

        The `MultipartFormField` object is used to represent fields in an HTTP
        request using `multipart/form-data`.


        ### Usage Example

        Create a `MultipartFormField` to define a multipart form entry.
      title: MultipartFormFieldRequest
    RequestFormatEnum:
      type: string
      enum:
        - JSON
        - XML
        - MULTIPART
      title: RequestFormatEnum
    DataPassthroughRequest:
      type: object
      properties:
        method:
          $ref: '#/components/schemas/MethodEnum'
        path:
          type: string
          minLength: 1
          description: The path of the request in the third party's platform.
        base_url_override:
          type:
            - string
            - 'null'
          minLength: 1
          description: An optional override of the third party's base url for the request.
        data:
          type:
            - string
            - 'null'
          minLength: 1
          description: >-
            The data with the request. You must include a `request_format`
            parameter matching the data's format
        multipart_form_data:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/MultipartFormFieldRequest'
          description: >-
            Pass an array of `MultipartFormField` objects in here instead of
            using the `data` param if `request_format` is set to `MULTIPART`.
        headers:
          type:
            - object
            - 'null'
          additionalProperties:
            description: Any type
          description: >-
            The headers to use for the request (Merge will handle the account's
            authorization headers). `Content-Type` header is required for
            passthrough. Choose content type corresponding to expected format of
            receiving server.
        request_format:
          oneOf:
            - $ref: '#/components/schemas/RequestFormatEnum'
            - type: 'null'
        normalize_response:
          type: boolean
          description: >-
            Optional. If true, the response will always be an object of the form
            `{"type": T, "value": ...}` where `T` will be one of `string,
            boolean, number, null, array, object`.
      required:
        - method
        - path
      title: DataPassthroughRequest
```

---

## Accessing Linked Account Credentials

Some third-party APIs require you to include credentials directly in the `path` or request body (`data`) when making Passthrough Requests to the third-party API on behalf of a linked account. You can securely access a linked account's stored credentials programmatically by including variables in double brackets (e.g. `{{USERNAME}}`).

Below is the full list of variables available for use in Passthrough Requests:

| Variable                         | Description                                                                                                                                                                                                                                                                                                                 |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `API_URL_SUBDOMAIN`              | Third-party API URL subdomain.                                                                                                                                                                                                                                                                                              |
| `API_KEY`                        | Third-party API Key.                                                                                                                                                                                                                                                                                                        |
| `USERNAME`                       | Basic auth username for third-party API.                                                                                                                                                                                                                                                                                    |
| `PASSWORD`                       | Basic auth password for third-party API.                                                                                                                                                                                                                                                                                    |
| `LINKED_ACCOUNT_ATTR.field_name` | If an account-specific credential is needed to make a request to a third-party API, and is not otherwise covered in the other variables, you can access it using this format. `field_name` represents the name of the field in the third-party API and should be replaced with that field name when using this in practice. |

\


### Example - Paylocity

This is an example request body that demonstrates how the `API_URL_SUBDOMAIN` variable can be used for Passthrough Requests to Paylocity's API.

**`Example request body`**

```json Example request body
{
  "method": "GET",
  "path": "/v2/companies/{{API_URL_SUBDOMAIN}}/employees/"
}
```

Some third-party APIs require you to encode credentials using Base64 encoding. You can specify what needs to be encoded into Base64 format in your third-party request by wrapping that content between `{BASE-64}` tags in the passthrough request body.

### Example - Workday

This is an example request body that demonstrates how the `BASE-64` method can be used for Passthrough Requests to Workday's API.

**`Example request body`**

```json Example request body
{
  "method": "GET",
  "path": "/service/customreport2/{{API_URL_SUBDOMAIN}}/100814/Demographic_Report?format=json",
  "headers": {
    "Authorization": "Basic {BASE-64}{{USERNAME}}:{{PASSWORD}}{BASE-64}"
  }
}
```

---

## Fetching with the Merge SDK

See below for an example of how to create an authenticated Passthrough Request with Merge's SDK:

```python
import merge
from merge.client import Merge


client = Merge(
    api_key="API_KEY",
    account_token="ACCOUNT_TOKEN",
)


passthrough_result = client.crm.passthrough.create(
    request=merge.resources.crm.types.DataPassthroughRequest(
        method="GET",
        path="/contacts/lists",
        request_format="JSON",
        base_url_override="https://override.baseurl.com",
    )
)
```

**`Ruby`**

```ruby Ruby
api_instance = MergeATSClient::PassthroughApi.new
passthrough_object = MergeATSClient::DataPassthrough.new
passthrough_object.method = 'GET'
passthrough_object.path = '/unique-data'
passthrough_object.headers = { "EXTRA-HEADER": 'value' }
begin
  result = api_instance.passthrough_create('YOUR_ACCOUNT_TOKEN', passthrough_object)
  puts result
rescue MergeATSClient::ApiError => e
  puts "Exception when calling passthrough_create: #{e}"
end
```

**`Node`**

```javascript Node
import { MergeClient, Merge } from '@mergeapi/merge-node-client';

const merge = new MergeClient({
  apiKey: 'YOUR_API_KEY',
  accountToken: 'YOUR_ACCOUNT_TOKEN',
});

// Define the data you want to send in the POST request
const requestData = {
  // Your request data goes here
  method: "POST",
  path: "/scooters",
  data: {"id": 123, "value": "ABC"},
  headers: {"EXTRA-HEADER": "header_value"},
};

// Make the POST request to /passthrough endpoint
merge.hris.passthrough.create(requestData)
  .then(response => {
    // Handle successful response
    console.log('Response:', response);
  })
  .catch(error => {
    // Handle error
    console.error('Error:', error);
  });
```

**`Go`**

```go Go
passthrough_object := merge_hris_client.NewDataPassthrough("GET", "/unique-data")
resp, r, err := api_client.PassthroughApi.PassthroughCreate(context.Background()).XAccountToken("YOUR_ACCOUNT_TOKEN").DataPassthrough(*passthrough_object).Execute()
```

**`Java`**

```java Java
import merge_ats_client.ApiClient;
import merge_ats_client.ApiException;
import merge_ats_client.api.PassthroughApi;
import merge_ats_client.model.DataPassthroughRequest;
import merge_ats_client.model.MethodEnum;
import merge_ats_client.model.RemoteResponse;

import java.util.HashMap;
import java.util.Map;

public class PassthroughRequest {

    public ApiClient getApiClient() {
        // See authentication documentation
    }

    public void sendPassthroughRequest() {
        ApiClient apiClient = getApiClient();
        PassthroughApi apiInstance = new PassthroughApi(getApiClient());

        DataPassthroughRequest dataPassthroughRequest = new DataPassthroughRequest();
        dataPassthroughRequest.setMethod(MethodEnum.POST);
        dataPassthroughRequest.setPath("/unique-data");
        Map<String, Object> data = new HashMap<>();
        data.put("id", 123);
        data.put("value", "ABC");
        dataPassthroughRequest.setData(data);
        dataPassthroughRequest.putHeadersItem("EXTRA-HEADER", "header_value");

        try {
            String xAccountToken = "END_USER_ACCOUNT_TOKEN";
            RemoteResponse result = apiInstance.passthroughCreate(xAccountToken, dataPassthroughRequest);
            System.out.println(result);
        } catch (ApiException e) {
            System.err.println("Exception when calling passthroughCreate: " + e);
        }
    }
}
```

**`Elixir`**

```ex Elixir
MergeATSClient.Api.Passthrough.passthrough_create(
  MergeATSClient.Connection.new(),
  "Bearer YOUR_PRODUCTION_KEY",
  "ACCOUNT_TOKEN",
  %MergeATSClient.Model.DataPassthrough{method: "GET", path: "/unique-data"}
)
```

---

## Response

The response to your query will look like the following:

**`Sample Response to Passthrough Request`**

```json Sample Response to Passthrough Request
{
  "method": "GET",
  "path": "/unique-data",
  "status": 200,
  "response": {
    "id": 23454,
    "value": "ABC"
  },
  "headers": {
    ...
    "Authorization": "<redacted>"
  }
}
```

The Passthrough Request endpoint will return a **408 status** if there is a timeout in getting the response. If you have experienced delays or timeouts with normal Passthrough Requests we recommend switching to use Merge's [Async Passthrough](/merge-unified/supplemental-data/passthrough-request/async-passthrough-requests) requests.