Troubleshooting Writes

Learn about the tools used to troubleshoot POST requests

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.

Example warning in POST response
1{
2 "model": {
3 "id": "521b18c2-4d01-4297-b451-19858d07c133"
4 "first_name": "Gil",
5 "last_name": "Feig",
6 "company": "Columbia Dining App.",
7 "title": "Software Engineer",
8 "applications": [
9 "application_1_id",
10 "application_2_id",
11 "application_3_id",
12 ],
13 "phone_numbers": [],
14 "email_addresses": [],
15 "urls": [],
16 "tags": [],
17 "attachments": [],
18 },
19 "warnings": [
20 {
21 "problem_type": "UNSUPPORTED_FIELD",
22 "title": "Unsupported Field",
23 "detail": "This request contained a field that is not supported in Candidate POST Requests to Greenhouse: stage",
24 "source": {
25 "pointer": "model/stage",
26 }
27 }
28 ]
29}

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.

Example error in POST response
1{
2 "model": {},
3 "warnings": [
4 {
5 "problem_type": "UNSUPPORTED_FIELD",
6 "title": "Unsupported Field",
7 "detail": "This request contained a field that is not supported in Candidate POST Requests to Greenhouse: stage",
8 "source": {
9 "pointer": "model/stage"
10 }
11 }
12 ],
13 "errors": [
14 {
15 "problem_type": "MISSING_REQUIRED_FIELD",
16 "title": "Missing Required Field",
17 "detail": "This request is missing a field required to POST a Candidate to Greenhouse: title",
18 "source": {
19 "pointer": "model/title"
20 }
21 }
22 ]
23}

Properties

PropertyDescription
problem_typeThe type of error or warning from Merge’s API.
titleA human-readable summary of the error or warning.
detailA description of what specifically caused the error or warning.
sourceIf 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.

Example of retry logic for a POST request
1async function createInvoice(invoice: InvoiceRequest): Promise<InvoiceResponse> {
2 const { accountToken, apiKey } = retrieveTokens();
3 const merge = new MergeClient({ apiKey, accountToken });
4 const maxRetries = 3;
5 let retryCount = 0;
6 let retryDelay = 5000; // initial delay of 5 seconds
7
8 while (true) {
9 try {
10 const response = await merge.accounting.invoices.create({
11 model: invoice
12 });
13 return response;
14 } catch (error) {
15 console.error(`Error creating invoice: ${error.message}`);
16
17 if (error.response.status === 429) {
18 // Too Many Requests, sleep for 60 seconds and retry
19 await new Promise(resolve => setTimeout(resolve, 60000));
20 } else if (error.response.status >= 500 && error.response.status < 600) {
21 // Server Error, retry with backoff
22 retryCount++;
23 if (retryCount <= maxRetries) {
24 await new Promise(resolve => setTimeout(resolve, retryDelay));
25 retryDelay *= 2; // exponential backoff
26 } else {
27 throw error;
28 }
29 } else {
30 throw error;
31 }
32 }
33 }
34}

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.

$GET https://api.merge.dev/api/ats/candidates/?is_debug_mode=true

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

Example logs in POST response
1{
2 "model": {},
3 "warnings": [
4 {
5 "problem_type": "UNSUPPORTED_FIELD",
6 "title": "Unsupported Field",
7 "detail": "This request contained a field that is not supported in Candidate POST Requests to Greenhouse: stage",
8 "source": {
9 "pointer": "model/stage",
10 }
11 }
12 ],
13 "errors": [
14 {
15 "problem_type": "MISSING_REQUIRED_FIELD",
16 "title": "Missing Required Field",
17 "detail": "This request is missing a field required to POST a Candidate to Greenhouse: title",
18 "source": {
19 "pointer": "model/title",
20 }
21 }
22 ],
23 "logs": [
24 {
25 "log_id": "3f70e9f7-af1c-472a-aec5-647298f649ec"
26 "dashboard_view": "https://app.merge.dev/logs/3f70e9f7-af1c-472a-aec5-647298f649ec",
27 "log_summary": {
28 "url": "https://harvest.greenhouse.io/sources/",
29 "method": "GET",
30 "status_code": 200,
31 }
32 },
33 {
34 "log_id": "fd8ccb65-7d4f-4799-87a8-346a1baaed77"
35 "dashboard_view": "https://app.merge.dev/logs/fd8ccb65-7d4f-4799-87a8-346a1baaed77",
36 "log_summary": {
37 "url": "https://harvest.greenhouse.io/candidates/",
38 "method": "POST",
39 "status_code": 500,
40 }
41 },
42 ]
43}

Each log in the response will contain the following properties:

PropertyDescription
log_idThe 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_viewA direct link to the log in Merge Dashboard.
log_summarySummary information about the log.
PropertyDescription
urlThe third-party API endpoint that the request from Merge was made to.
methodThe type of request that Merge made to the third-party API endpoint.
status_codeThe status code received by Merge in the response from the third-party API endpoint.