Appearance
Fresh 2026
Troubleshooting Writes
Tools and techniques for debugging failed write requests, including the Merge Dashboard audit log and API response diagnostics.
Overview
Merge's API provides tools that allow you to easily troubleshoot any issues with POST requests to Merge.
This consists of:
- Unified error and warning messaging directly within API responses
- Optional debug mode that lists logs of requests made from Merge to the relevant third-party API associated with the POST request to Merge
View the full list of possible errors and warnings in Writes Errors and Warnings Reference.
Warnings and errors
The warnings field contains details on issues that don't stop the request from being successful.
The errors field contains details on issues that cause the request to fail.
Warnings
Warnings in POST responses notify you about issues with the request that did not prevent the Common Model instance from being created.
For example, if the request contains an unrecognized field, we will ignore the field and notify you with a warning in the response.
json
{
"model": {
"id": "521b18c2-4d01-4297-b451-19858d07c133"
"first_name": "Gil",
"last_name": "Feig",
"company": "Columbia Dining App.",
"title": "Software Engineer",
"applications": [
"application_1_id",
"application_2_id",
"application_3_id",
],
"phone_numbers": [],
"email_addresses": [],
"urls": [],
"tags": [],
"attachments": [],
},
"warnings": [
{
"problem_type": "UNSUPPORTED_FIELD",
"title": "Unsupported Field",
"detail": "This request contained a field that is not supported in Candidate POST Requests to Greenhouse: stage",
"source": {
"pointer": "model/stage",
}
}
]
}For a list of possible errors and warnings returned by Merge's API's POST endpoints, check out the Warnings and Errors Reference.
Errors
Errors in POST responses notify you about issues with the request that prevented the Common Model instance from being created.
For example, if the request was missing a required field, then we will not create the Common Model instance and return an error response instead.
json
{
"model": {},
"warnings": [
{
"problem_type": "UNSUPPORTED_FIELD",
"title": "Unsupported Field",
"detail": "This request contained a field that is not supported in Candidate POST Requests to Greenhouse: stage",
"source": {
"pointer": "model/stage"
}
}
],
"errors": [
{
"problem_type": "MISSING_REQUIRED_FIELD",
"title": "Missing Required Field",
"detail": "This request is missing a field required to POST a Candidate to Greenhouse: title",
"source": {
"pointer": "model/title"
}
}
]
}Properties
| Property | Description |
|---|---|
problem_type | The type of error or warning from Merge's API. |
title | A human-readable summary of the error or warning. |
detail | A description of what specifically caused the error or warning. |
source | If applicable, this property denotes the ID of the source of the error / warning |
Automatic retry
It's generally best practice to have pre-defined retry logic when encountering specific error codes (429 or 5XX). Merge does not recommend retrying for other error codes. In the provided POST request example using our Node SDK, the retry logic handles errors based on HTTP status codes with an exponential backoff strategy.
If the request encounters a 429 Too Many Requests error, the logic waits for 60 seconds before retrying. For server errors (status codes 500-599), the code retries up to a maximum of 3 attempts, with each retry delay doubling (exponentially increasing) from an initial 5-second delay. If the maximum retries are reached or if an error falls outside these categories, the error is thrown. This ensures that transient issues like rate limits or server outages are gracefully handled with retries, while persistent issues are promptly reported.
typescript
async function createInvoice(invoice: InvoiceRequest): Promise {
const { accountToken, apiKey } = retrieveTokens();
const merge = new MergeClient({ apiKey, accountToken });
const maxRetries = 3;
let retryCount = 0;
let retryDelay = 5000; // initial delay of 5 seconds
while (true) {
try {
const response = await merge.accounting.invoices.create({
model: invoice
});
return response;
} catch (error) {
console.error(`Error creating invoice: ${error.message}`);
if (error.response.status === 429) {
// Too Many Requests, sleep for 60 seconds and retry
await new Promise(resolve => setTimeout(resolve, 60000));
} else if (error.response.status >= 500 && error.response.status setTimeout(resolve, retryDelay));
retryDelay *= 2; // exponential backoff
} else {
throw error;
}
} else {
throw error;
}
}
}
}Tip: Use the Idempotency-Key header to avoid creating duplicate records.
Debug Mode
Logs of requests made from Merge to third-party platforms are available for transparency.
Debug Mode makes it easy to retrieve the logs for requests made from Merge to a third-party's API as a result of a POST request to Merge.
This is most useful for cases where detail beyond the standard errors and warnings from Merge is helpful to troubleshoot, for example:
- Troubleshooting errors stemming from the third-party API (see error type
PROVIDER_ERROR) - Troubleshooting generic errors from Merge (see error type
ERROR)
Usage
To use Debug Mode, include is_debug_mode=true as a query parameter in the POST request.
bash
GET https://api.merge.dev/api/ats/candidates/?is_debug_mode=trueIn Debug Mode, the response includes the logs field, which is an array of log objects containing detail on outbound requests made to the end user's API provider during the request.
json
{
"model": {},
"warnings": [
{
"problem_type": "UNSUPPORTED_FIELD",
"title": "Unsupported Field",
"detail": "This request contained a field that is not supported in Candidate POST Requests to Greenhouse: stage",
"source": {
"pointer": "model/stage",
}
}
],
"errors": [
{
"problem_type": "MISSING_REQUIRED_FIELD",
"title": "Missing Required Field",
"detail": "This request is missing a field required to POST a Candidate to Greenhouse: title",
"source": {
"pointer": "model/title",
}
}
],
"logs": [
{
"log_id": "3f70e9f7-af1c-472a-aec5-647298f649ec"
"dashboard_view": "https://app.merge.dev/logs/3f70e9f7-af1c-472a-aec5-647298f649ec",
"log_summary": {
"url": "https://harvest.greenhouse.io/sources/",
"method": "GET",
"status_code": 200,
}
},
{
"log_id": "fd8ccb65-7d4f-4799-87a8-346a1baaed77"
"dashboard_view": "https://app.merge.dev/logs/fd8ccb65-7d4f-4799-87a8-346a1baaed77",
"log_summary": {
"url": "https://harvest.greenhouse.io/candidates/",
"method": "POST",
"status_code": 500,
}
},
]
}Each log in the response will contain the following properties:
| Property | Description |
|---|---|
log_id | The ID of the log in Merge, which can be used to get more detail on the log by: 1. Sending a GET request to /api/logs/{log_id} 2. Viewing it in the Merge App by going to https://app.merge.dev/logs/{log_id} |
dashboard_view | A direct link to the log in Merge Dashboard. |
log_summary | Summary information about the log. |
| Property | Description |
|---|---|
url | The third-party API endpoint that the request from Merge was made to. |
method | The type of request that Merge made to the third-party API endpoint. |
status_code | The status code received by Merge in the response from the third-party API endpoint. |