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

# Programmatic Writes with /meta

> How to use the /meta endpoint to discover required and optional fields before making a POST request. Fields vary by integration and Linked Account.

---

## Introducing `/meta`

Merge's Common Models have most fields you need, but there are advanced use cases where the fields available for POST requests to Merge change based on the third-party platform or user.

Merge's `/meta` endpoint helps you account for these use cases by dynamically fetching `model` field names, types, and other metadata used for making writes **to a given integration or Linked Account.**

Instead of building customized logic for every integration, `/meta` allows you to:

* Dynamically prompt users for **required** / **optional** and **standard** / **non-standard** fields
* Build once to create or update data for **all third-party platforms**
* Programmatically account for **Linked Account differences and customizations**
* **Validate** POST requests for all required information

> **Info**
>
> `/meta` can be useful for generating UIs and forms within your application where the prompts change based on the user.

**`Example /meta response`**

```json title="Example /meta response"
{
  "request_schema": {
    "type": "object",
    "properties": {
      "model": {
        "type": "object",
        "properties": {
          "first_name": {
            "type": "string",
            "description": "The candidate's first name."
          },
          "last_name": {
            "type": "string",
            "description": "The candidate's last name."
          },
          "email_addresses": {
            "type": "array",
            "description": "Array of email_addresses objects on ats.Candidate",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "email_address_type": {
                  "type": "string"
                }
              },
              "required": ["value"]
            }
          }
        },
        "required": ["first_name", "last_name", "email_addresses"]
      }
    },
    "required": ["model"]
  }
}
```

---

## GET Request to `/meta`

All Merge POST endpoints have an associated `/meta` GET endpoint.

For example, to get the integration- or account-specific schema for a successful POST request to `/candidates`, make a GET request to `/candidates/meta/post` first.

### Account Token

To identify the specific integration and Linked Account, pass the `account_token` for the Linked Account you are looking to write data to in the header of your API request.

> **Info**
>
> Refer to our guide to [Authentication](/basics/authentication) to learn more about using `account_tokens`.

---

## Response from `/meta`

The response from `/meta` will return requirements for writing data to a specific integration or Linked Account.

The response will contain three components:

* `request_schema`
* `status`
* booleans that make it easier to work with `request_schema` and build programmatic flows

### `request_schema`

The `request_schema` object is the bulk of the `/meta` response and contains details about the `model` fields for the POST request specific to the integration or Linked Account.

Specifically, `model` in the `/meta` response will have the following properties:

| `model` Property        | Description                                                                                                                                                                                                                                                                                                               |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Common Model fields     | The Common Model fields listed here are writable to the integration or Linked Account.                                                                                                                                                                                                                                    |
| `integration_params`    | Integration-specific writable `model` fields not part of Merge's Common Model.                                                                                                                                                                                                                                            |
| `linked_account_params` | Linked Account-specific writable `model` fields not part of Merge's Common Model.                                                                                                                                                                                                                                         |
| `remote_template_id`    | In some cases, this enum input from your user determines whether there are additional field inputs required from your user. Learn more in our guide to [Programmatic Writes with /meta for Fields Conditional on User Input](/merge-unified/writing-data/programmatic-writes-with-meta/templates-and-conditional-fields). |

> **Info**
>
> Merge uses **JSON Schema** conventions in `request_schema` for scalable schemas and programmatic convenience.
>
> Learn more in our guide to [Schema Properties](/merge-unified/specifications/schema-properties).

#### Common Model Fields

Given the natural differences in third-party platforms, the `request_schema` is useful for determining **writability** and **optionality** of each Common Model field for each integration.

##### Example - Request Schema

See an example of a basic `request_schema` below:

#### Example request\_schema

```json {5-35}
{
    "request_schema": {
        "type": "object",
        "properties": {
            "model": {
                "type": "object",
                "properties": {
                    "first_name": {
                        "type": "string",
                        "description": "The candidate's first name."
                    },
                    "last_name": {
                        "type": "string",
                        "description": "The candidate's last name."
                    },
                    "email_addresses": {
                        "type": "array",
                        "description": "Array of email_addresses objects on ats.Candidate",
                        "items": {
                            "type": "object",
                            "properties": {
                                "value": {
                                    "type": "string",
                                },
                                "email_address_type": {
                                    "type": "string",
                                }
                            },
                            "required": ["value"]
                        }
                    }
                },
                "required": ["first_name", "last_name", "email_addresses"]
            }
        },
        "required": ["model"]
    }
}
```

##### Example - Request Body

In accordance with the response from /meta above, the POST request you would form might have a body like this:

#### Example POST request body

```json
{
  "model": {
    "first_name": "Jane",
    "last_name": "Doe",
    "email_addresses": [
      {
        "value": "jane@merge.dev",
        "email_address_type": "WORK"
      },
      {
        "value": "jane@gmail.com",
        "email_address_type": "PERSONAL"
      }
    ]
  }
}
```

#### Non-Common Model Fields

In addition to Common Model fields, some integrations and Linked Accounts may have varying writable **Non-Common Model fields** (fields not part of Merge's standardized data model).

These fields are contained in `integration_params` and `linked_account_params`.

##### Integration-Specific Fields (`integration_params`)

Non-Common Model fields that are **specific to certain third-party platforms** will be contained in `integration_params`.

##### Example - Request Schema

Let's say an ATS platform requires a `stage` field for newly created `Candidates`, even though this field is not included in our Common Model.

As a result, the `Candidate's stage` must be added to `model` in the body of POST requests to Merge for this specific third-party platform.

The `request_schema` for this integration may look like:

#### Example request\_schema

```json {32-51}
{
    "request_schema": {
        "type": "object",
        "properties": {
            "model": {
                "type": "object",
                "properties": {
                    "first_name": {
                        "type": "string",
                        "description": "The candidate's first name."
                    },
                    "last_name": {
                        "type": "string",
                        "description": "The candidate's last name."
                    },
                    "email_addresses": {
                        "type": "array",
                        "description": "Array of email_addresses objects on ats.Candidate",
                        "items": {
                            "type": "object",
                            "properties": {
                                "value": {
                                    "type": "string",
                                },
                                "email_address_type": {
                                  "type": "string",
                                }
                            },
                            "required": ["value"], 
                        }
                    },
                    "integration_params": {
                        "type": "object",
                        "properties": {
                            "stage": {
                                "type": "string",
                                "enum": ["ARCHIVED", "ACTIVE"],
                                "enum_information": [
                                    {
                                        "value": "ARCHIVED",
                                        "description": "Archived"
                                    },
                                    {
                                        "value": "ACTIVE",
                                        "description": "Active"
                                    }
                                ]
                            }
                        },
                        "required": ["stage"]
                    }
                },
                "required": ["first_name", "last_name", "email_addresses"]
            }
        },
        "required": ["model"]
  }
}
```

##### Example - Request Body

In accordance with the response from `/meta` above, the POST request you would form might have a body like this:

#### Example POST request body

```json {15-16}
{
  "model": {
    "first_name": "Jane",
    "last_name": "Doe",
    "email_addresses": [
      {
        "value": "jane@merge.dev",
        "email_address_type": "WORK",
      },
      {
        "value": "jane@gmail.com",
        "email_address_type": "PERSONAL",
      }
    ],
    "integration_params": {
      "stage": "ACTIVE"
    }
  }
}
```

If you are writing to an integration with an integration-specific Non-Common Model field with **consistent enum choices** across all Linked Accounts (like `Archived` and `Active` in the above example), then it may be unnecessary to use `/meta` to dynamically form POST requests since you can anticipate the choices for the field.

However, if that integration-specific field has **enum choices that vary by Linked Account**, then it would be necessary to use `/meta` to dynamically surface the enum choices to your user.

**Example:**

Instead of `stage` having fixed enum options of `Archived` and `Active`, let's say that **different Linked Accounts** for the same integration have **varying enum choices** for the `stage` field (which is not part of Merge's `Candidate` Common Model).

For example, **Linked Account A** could have `Archived` and `Active` stages and **Linked Account B** could have `Unprocessed` and `Processed` stages (illustrated below).

When passing the different Linked Account tokens in your GET request to `/meta`, the `integration_params` object in each `/meta` response would look like the following:

**Linked Account A**

```json {6-19}
"integration_params": {
  "type": "object",
  "properties": {
    "stage": {
      "type": "string",
      "enum": [
          "ARCHIVED", 
          "ACTIVE"
      ],
      "enum_information": [
        {
          "value": "ARCHIVED",
          "description": "Archived"
        },
        {
          "value": "ACTIVE",
          "description": "Active"
        }
      ]
    }
  },
  "required": ["stage"], 
}
```

**Linked Account B**

```json {6-19}
"integration_params": {
  "type": "object",
  "properties": {
    "stage": {
      "type": "string",
      "enum": [
          "UNPROCESSED", 
          "PROCESSED"
      ],
      "enum_information": [
        {
          "value": "UNPROCESSED",
          "description": "Unprocessed"
        },
        {
          "value": "PROCESSED",
          "description": "Processed"
        }
      ]
    }
  },
  "required": ["stage"], 
}
```

##### Linked Account-Specific Fields (`linked_account_params`)

Non-Common Model fields that are **specific to Linked Accounts** will be contained within the `linked_account_params` object within the `request_schema`.

##### Example - Request Schema

An ATS integration can allow a Linked Account to specify that a `hackerrank_score` is required when creating a `Candidate`.

Since `hackerrank_score` isn't a field in Merge's `Candidate` Common Model and it's writability depends on the Linked Account's configuration, you would use `/meta` to determine whether this input is required from your user.

Here is an example `/meta` response denoting the `hackerrank_score` field as required for the given Linked Account:

#### Example request\_schema with linked\_account\_params

```json {32-39}
{
    "request_schema": {
        "type": "object",
        "properties": {
            "model": {
                "type": "object",
                "properties": {
                    "first_name": {
                        "type": "string",
                        "description": "The candidate's first name."
                    },
                    "last_name": {
                        "type": "string",
                        "description": "The candidate's last name."
                    },
                    "email_addresses": {
                        "type": "array",
                        "description": "Array of email_addresses objects on ats.Candidate",
                        "items": {
                            "type": "object",
                            "properties": {
                                "value": {
                                    "type": "string",
                                },
                                "email_address_type": {
                                    "type": "string",
                                }
                            }
                        }
                    },      
                    "integration_params": null,
                    "linked_account_params": {
                        "type": "object",
                        "properties": {
                            "hackerrank_score": {
                                "type": "number",
                            }
                        },
                        "required": ["hackerrank_score"]
                    }
                },
                "required": ["first_name", "last_name"]
            }
        },
        "required": ["model"]
    }
}
```

##### Example - Request Body

In accordance with the response from `/meta` above, the POST request you would form might have a body like this:

#### Example POST request body

```json {15-16}
{
  "model": {
    "first_name": "Jane",
    "last_name": "Doe",
    "email_addresses": [
      {
        "value": "jane@merge.dev",
        "email_address_type": "WORK",
      },
      {
        "value": "jane@gmail.com",
        "email_address_type": "PERSONAL",
      }
    ],
    "linked_account_params": {
      "hackerrank_score": 100
    }
  }
}
```

### `status`

The `status` object within `/meta` can tell you if an integration is down or if a Linked Account is not properly connected, either of which will block POST requests.

`status` has three properties:

| Property                | Type    | Options                     | Description                                                                                                                          |
| ----------------------- | ------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `integration_status`    | Enum    | `OK`, `DOWN`                | Operational status of integration.                                                                                                   |
| `linked_account_status` | Enum    | `COMPLETE`, `RELINK_NEEDED` | Connection status of Linked Account.                                                                                                 |
| `can_make_request`      | boolean | `true`, `false`             | Returns `true` if `integration_status` is `OK` and `linked_account_status` is `COMPLETE`. This property is included for convenience. |

> **Info**
>
> If the Linked Account is not properly linked and shows a status of `RELINK_NEEDED`, you can find additional error details in your [Linked Accounts dashboard](https://app.merge.dev/linked-accounts/accounts/).

### Helper Variables

The `/meta` response also includes a few helper variables for convenience:

| Property                             | Type    | Options         | Description                                                                                                |
| ------------------------------------ | ------- | --------------- | ---------------------------------------------------------------------------------------------------------- |
| `has_required_linked_account_params` | boolean | `true`, `false` | Returns `true` if there are required Linked Account-specific fields contained within the `/meta` response. |
| `has_conditional_fields`             | boolean | `true`, `false` | Returns `true` if there are POST request fields conditional on your user's input in another field.         |

> **Info**
>
> Learn more about what to do when `has_conditional_fields` is `true` in our guide to [Templates and Conditional Fields](/merge-unified/writing-data/programmatic-writes-with-meta/templates-and-conditional-fields).