Skip to main content
This guide covers the responses and errors developers most frequently encounter with the Finch API. Null values and 202 responses are expected parts of a normal response — but your application can misbehave if it doesn’t handle them. Server errors, reauthentication errors, and rate limit errors are true error conditions Finch returns when something goes wrong. Your application should expect and handle the error types documented in the API reference.

Null values

A null value isn’t an error — it’s an expected response value. See Null Values for why Finch returns null and how to check for it.

202 responses

A 202 response isn’t an error either — it means the connection exists but data isn’t available yet. See 202 Response Codes for the retry and backoff behavior your application should implement, or Testing assisted integrations to reproduce a 202 response in the Finch Sandbox.

Server errors

Server errors (HTTP 500) are uncommon but possible. A few error-handling mechanisms help you maintain a good user experience while diagnosing the issue:
  • Friendly error page. Display a user-friendly message instead of the raw server error to maintain user trust.
  • Log the error. Capture the error message, stack trace, request details, and other relevant context. Always log the finch-request-id from the HTTP response headers — Finch needs it to diagnose the issue on our side.
  • Health checks. Call the /introspect endpoint on a regular basis to monitor the status of your Finch integration and its connections — this helps you identify the source of 500 errors faster.
  • Retry. Retry the request after a delay, or adjust the request parameters — this resolves many transient server errors.
Product outages. Finch reports all API outages and provider integration incidents at status.tryfinch.com — subscribe there for email notifications when Finch creates, updates, or resolves an incident.
If a server error persists, contact Finch Support and attach the finch-request-id from the response headers.

Retry example

Finch may also return 4XX or 5XX error types due to unsupported responses from the underlying employment system. Retrying immediately may not resolve the issue — the following example retries a failed request with a fixed delay:
Error handling example
function fetchDataWithRetry(url, options, retries = 3, delay = 2000) {
  return fetch(url, options)
    .then(response => {
      if (response.status === 500 && retries > 0) {
        return new Promise(resolve => setTimeout(resolve, delay))
          .then(() => fetchDataWithRetry(url, options, retries - 1, delay));
      } else {
        return response;
      }
    })
    .catch(error => console.error('Error:', error));
}

fetchDataWithRetry(url, {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json',
  },
})
.then(response => response.json())
.then(data => console.log(data));

Reauthentication errors

A reauthentication error means the credentials Finch uses to access an employer’s provider system no longer work, and the employer must reauthenticate. This returns an HTTP status code of 401 Unauthorized with a finch_code of reauthenticate_user (see Finch API errors). To handle this error:
  1. Catch 401 responses with a finch_code of reauthenticate_user in your Finch API error handling.
  2. Create a new Finch Connect session for the connection using the /connect/sessions/reauthenticate endpoint, passing the connection’s connection_id. If your application doesn’t already store the connection_id, retrieve it by calling /introspect with the connection’s access_token.
  3. Direct the employer to complete Finch Connect through your existing flow — for example, prompt them to log in to your application dashboard, or send them a link to reauthenticate.
  4. Exchange the resulting authorization code for a new access token — this is the same access token exchange used during initial setup.
See Reauthentication for what causes this error and how to handle multi-entity connections, employee permissions, and product scopes when reauthenticating.

Rate limit errors

Finch returns a rate limit error with the HTTP status code 429 Too Many Requests when an application or IP address exceeds its request limit. Review the API rate limits before continuing. Finch’s rate limits work on a per-endpoint basis for applications. Finch calls each distinct endpoint a unique product, and sums rate limits on a rolling 60-second basis per product — commonly called a sliding or rolling window rate limit. Think of each product’s rate limit as a bucket. Every request to a product (which maps to an API endpoint) adds a gallon of water to that endpoint’s bucket and starts a 60-second time-to-live (TTL) timer. When the bucket empties after 60 seconds, the next request restarts the TTL. Stay within these rate limits to avoid request failures. If you hit a rate limit error, implement a back-off and retry strategy: wait 60 seconds for the bucket to reset, then retry, increasing the wait time exponentially on repeated failures.

Batch requests

Batch requests instead of calling an endpoint once per ID, to reduce your request count and avoid exhausting your rate limit.

Rate Limit Scenario

This scenario shows how an application encounters application-level rate limits. Assume your application has five access tokens (Token A–E) making requests to the company, directory, individual, employment, payment, and pay-statement endpoints. Each request to an endpoint adds a gallon of water to that product’s application-level bucket. The bucket counts requests across all of the application’s access tokens (Token A–E). Organization endpoints have a capacity of 20 max requests per minute. Pay endpoints have a capacity of 12 max requests per minute.
Each step below happens within the same 60-second (1-minute) time window.
  1. Token A makes 5 requests to /company, 4 to /directory, and 3 to /payment within a minute. Each bucket is below its capacity, so all of Token A’s requests succeed.
    • Application-level rate limits
      BucketCapacity
      company5/20 - success
      directory4/20 - success
      individual0/20
      employment0/20
      payment3/12 - success
      pay-statement0/12
  2. Token B makes 5 more requests to /company, 4 to /directory, and 3 to /payment within the same minute. Each bucket is still below capacity, so all of Token B’s requests succeed.
    • Application-level rate limits
      BucketCapacity
      company10/20 - success
      directory8/20 - success
      individual0/20
      employment0/20
      payment6/12 - success
      pay-statement0/12
  3. Tokens C and D each repeat the same pattern — 5 requests to /company, 4 to /directory, and 3 to /payment — within the same minute. The company and payment buckets reach full capacity, but Token C’s and D’s requests still succeed because the limits haven’t been exceeded yet.
    • Application-level rate limits
      BucketCapacity
      company20/20 (FULL) - success
      directory16/20 - success
      individual0/20
      employment0/20
      payment12/12 (FULL) - success
      pay-statement0/12
  4. Token E then makes 1 request to /company and 1 to /directory. The company and payment buckets are now full, so any further request to those endpoints — including Token E’s /company request — returns a 429 rate limit error until the 60-second TTL resets. Token E’s /directory request succeeds because that bucket isn’t full yet. Only successful requests count toward the application-level limit.
    • Application-level rate limits
      BucketCapacity
      company20/20 (FULL) - error
      directory16/20 - success
      individual0/20
      employment0/20
      payment12/12 (FULL) - error
      pay-statement0/12
Every fifth request to /company for each token fails with a 429 rate limit error once its bucket is full.

Rate limit example

The following RateLimiter class enforces this quota at the application level. Initialized with a limit (for example, 20 requests per minute for /directory), it makes requests up to that limit and pauses further requests until the bucket resets after 60 seconds. Call its request method to make API requests through the rate limiter, and initialize a separate RateLimiter instance for each endpoint you call.
class RateLimiter {
  constructor(limit) {
    this.limit = limit;
    this.requests = [];
  }

  async request(fn) {
    const now = Date.now();
    this.requests = this.requests.filter((timestamp) => now - timestamp < 60000);

    if (this.requests.length >= this.limit) {
      const delay = this.requests[0] + 60000 - now;
      await new Promise((resolve) => setTimeout(resolve, delay));
      this.requests.shift();
    }

    this.requests.push(now);
    return fn();
  }
}

const directoryRateLimiter = new RateLimiter(20); // 20 requests per minute
const url = 'https://api.tryfinch.com/employer/directory'; // Replace with the desired endpoint
const accessToken = '<your_access_token>';

const fetchIndividualData = (
) =>
  fetch(url, {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
  });

// Use the rate limiter to make API requests
directoryRateLimiter
  .request(fetchIndividualData)
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error('Error:', error));

Checkpoint + Next Step

Your application can now handle Finch’s most common error scenarios, making your integration more resilient. Monitoring API requests makes error mitigation easier — see Monitor API Usage next.

Learn more