> ## Documentation Index
> Fetch the complete documentation index at: https://docs.signalhire.com/llms.txt
> Use this file to discover all available pages before exploring further.

# FAQ

> Frequently asked questions about the SignalHire API.

## General

<AccordionGroup>
  <Accordion title="Do I need a separate subscription to use the API?">
    No. API access uses the same credits and quotas as the SignalHire website and browser extension. There is no separate API subscription. The Company API is the only exception — it requires a separate request to support to enable.
  </Accordion>

  <Accordion title="Where do I get an API key?">
    In the SignalHire web app, open the left sidebar and navigate to **Other tools → Integrations & API**. Click **Create new API Key** and copy the generated key. See [Authentication](/authentication) for details.
  </Accordion>

  <Accordion title="How do I know how many credits I have left?">
    Every API response includes the `X-Credits-Left` header with the current balance. For standard credits, the value updates automatically after each request. Credits can also be checked explicitly via the [Get Remaining Credits](/person-api/credits) endpoint.
  </Accordion>
</AccordionGroup>

***

## Credits

<AccordionGroup>
  <Accordion title="What credit types does SignalHire API use?">
    There are three independent credit types:

    * **Standard credits** — used by the Person API when fetching profiles with contacts. Shared across the website, browser extension, and API.
    * **Without-contacts credits** — used by the Person API with `withoutContacts: true`. Independent from standard credits. Contact [support@signalhire.com](mailto:support@signalhire.com) to purchase.
    * **Company data credits** — used by `/company/info`. Independent from all other credit types. Part of the Company API which requires separate access. Contact [support@signalhire.com](mailto:support@signalhire.com) to purchase.

    The `X-Credits-Left` response header always reflects the balance of the credit type relevant to the request made.
  </Accordion>

  <Accordion title="Are API credits shared with the website and browser extension?">
    Standard credits are shared — any usage on the website, browser extension, or API draws from the same balance. Without-contacts credits and company data credits are API-only and have no equivalent on the website.
  </Accordion>

  <Accordion title="How do I check my remaining balance for each credit type?">
    Use the [Get Remaining Credits](/person-api/credits) endpoint:

    * Standard credits: `GET /api/v1/credits`
    * Without-contacts credits: `GET /api/v1/credits?withoutContacts=true`

    For company data credits, check the `X-Credits-Left` header returned by `/company/info`.
  </Accordion>

  <Accordion title="When exactly is a credit consumed?">
    A credit is consumed at the moment a profile is successfully matched — not when the callback is delivered. If the callback fails to reach the endpoint, the credit is still charged. To retrieve the data, a new API request must be submitted, which will consume credits again.
  </Accordion>
</AccordionGroup>

***

## Person API

<AccordionGroup>
  <Accordion title="Why do I need to set up a callback URL? Can't I just get the result directly?">
    The default async mode requires a callback because the API queries multiple external sources to maximize contact coverage — this takes time. If a simpler flow is needed without setting up a server endpoint, use [`withoutWaterfall: true`](/person-api/without-waterfall). Results will be returned synchronously in the response, though contact coverage may be slightly lower.
  </Accordion>

  <Accordion title="How do I authenticate incoming callbacks to my endpoint?">
    Custom HTTP headers in the `callbackUrl` are not supported — SignalHire POSTs to the provided URL without additional headers. Two recommended patterns for production:

    **1. Secret token in the callback URL**

    ```
    https://yourdomain.com/callback/{secret}
    https://yourdomain.com/callback?token=your_secret_token
    ```

    Generate a unique token, embed it in the URL, and verify it on your server against the expected value. This is sufficient for most production use cases.

    **2. IP allowlisting**
    All callbacks originate from SignalHire servers — incoming requests can be restricted by IP. This is less reliable as IPs may change, so it's better used as an additional layer rather than the sole mechanism.
  </Accordion>

  <Accordion title="My callback URL never receives a response. What's wrong?">
    The most common causes: the callback URL is not publicly accessible, it times out (SignalHire waits up to 10 seconds), or it doesn't respond with HTTP `200`. If delivery fails after 3 retries, the callback is discarded. SignalHire sends an email notification with the affected request IDs — check your inbox and resubmit the failed requests. See [Callback Delivery](/person-api/retrieve-person#callback-delivery) for details.
  </Accordion>

  <Accordion title="I submitted a request but nothing came to my callback. Was I charged?">
    Credits are consumed at the moment a profile is matched — regardless of whether the callback was successfully delivered. If the callback failed, the credit was still charged. The request IDs of undelivered callbacks appear in the email notification sent by SignalHire. To get the data, submit a new API request with those identifiers.
  </Accordion>

  <Accordion title="Can I mix LinkedIn URLs, emails, and phone numbers in a single request?">
    Yes. The `items` array accepts any combination of LinkedIn URLs, email addresses, phone numbers, and 32-character SignalHire UIDs in a single request — up to 100 items per request.
  </Accordion>

  <Accordion title="What does status 'failed' in the callback mean?">
    The profile could not be found in the database, or the identifier provided did not match any known profile. No credits are consumed for failed items.
  </Accordion>

  <Accordion title="What is the difference between withoutContacts and withoutWaterfall?">
    They are independent options. `withoutContacts: true` controls **what** is returned — profile data without emails and phone numbers, using a separate credit type that must be purchased via [support@signalhire.com](mailto:support@signalhire.com). `withoutWaterfall: true` controls **how** results are delivered — synchronously in the response instead of via callback, without querying external sources.
  </Accordion>

  <Accordion title="How long should I wait for a callback before assuming it was lost?">
    There is no fixed maximum delivery time. SignalHire queries external APIs in real time for each request — most callbacks arrive within a few seconds, though some may take 30–60 seconds or more depending on external API response times. There is no server-side timeout that would cause a callback to be silently dropped. The callback is always sent once processing completes. If a callback never arrives, check the failed delivery email notification from SignalHire and resubmit the affected request IDs.
  </Accordion>

  <Accordion title="I can't set up a public callback server. Can I still use the Person API?">
    Yes. Use [`withoutWaterfall: true`](/person-api/without-waterfall) — it returns results synchronously in the response body without requiring a callback URL. This is particularly useful for local development, scripts, or environments where setting up a publicly accessible endpoint is not practical. Keep in mind that contact coverage may be lower than in standard async mode, as only contacts already cached in the database are returned.
  </Accordion>

  <Accordion title="Does withoutWaterfall return contact details?">
    Yes, but only contacts already present in the SignalHire database at the time of the request. No external API queries are made, so the contact coverage may be lower than in standard async mode. The `contacts` array may be empty for profiles where no contacts have been cached yet.
  </Accordion>
</AccordionGroup>

***

## Search API

<AccordionGroup>
  <Accordion title="Why does the scrollId expire after only 15 seconds?">
    The 15 seconds is the window between consecutive scroll requests, not the total session duration. The server keeps the search context alive for the whole session — as long as each next request arrives within 15 seconds of the previous response, the session stays active indefinitely. The scroll is designed for continuous sequential fetching, not for periodic polling.
  </Accordion>

  <Accordion title="Can I save the scrollId and resume the search later?">
    No. Once a `scrollId` expires (15 seconds after it was issued), the scroll session is lost and cannot be resumed. The correct approach is to fetch all batches in one continuous session, save each batch to the database as it arrives, and process everything afterwards.
  </Accordion>

  <Accordion title="Does each scrollSearch call count as a new search against my daily quota?">
    No. Only `searchByQuery` calls count as searches. However, every profile returned by both `searchByQuery` and `scrollSearch` counts against the daily profile quota. Both limits — queries and profiles — are tracked independently.
  </Accordion>

  <Accordion title="My location string returns a 422 error. What formats are accepted?">
    The location field accepts country names (`"Germany"`), US and Canadian states (`"California"`, `"Ontario, Canada"`), and city strings (`"London, United Kingdom"`). The value must be recognizable — if it cannot be resolved, a `422` is returned. For precise searches, use `latitude`/`longitude` or `coordinates` instead, which bypass text resolution entirely. See [Location Formats](/search-api/search-by-query#location-formats).
  </Accordion>

  <Accordion title="Can I use excludeRevealed without any other filters?">
    No. All exclude filters (`excludeRevealed`, `excludeWatched`, `excludeInLists`, `excludeInProgress`, `excludeEmailed`) must be combined with at least one non-exclude filter such as `currentTitle` or `industry`. A request with only exclude filters returns `422`.
  </Accordion>

  <Accordion title="The Search API returns profiles without contact details. How do I get their contacts?">
    Use the `uid` field from each search profile and pass it to the [Person API](/person-api/retrieve-person). The Person API will return the full profile including emails and phone numbers. Standard credits are consumed for each successfully matched profile.
  </Accordion>

  <Accordion title="Why is my daily search quota shared with the website?">
    The API and the SignalHire web app both run on the same account, so all searches — regardless of where they originate — draw from the same daily allowance. This is by design to ensure fair usage across all channels.
  </Accordion>
</AccordionGroup>

***

## Company API

<AccordionGroup>
  <Accordion title="How do I get access to the Company API?">
    The Company API is not enabled by default. Contact [support@signalhire.com](mailto:support@signalhire.com) to request access and purchase the required credits.
  </Accordion>

  <Accordion title="Does /company/getProfiles use its own credit type?">
    No. `/company/getProfiles` does not consume a purchasable credit at all — each profile delivered counts against the same daily profile-view quota shared with the SignalHire website.
  </Accordion>

  <Accordion title="What happens when I exceed the getProfiles daily quota?">
    The endpoint returns HTTP `429` with a message indicating the daily profile-view quota has been reached. The quota varies by plan, up to 2000 profiles/day. Contact [support@signalhire.com](mailto:support@signalhire.com) if you consistently need a higher limit.
  </Accordion>

  <Accordion title="Can I search companies by name?">
    Not directly. Use `/company/findById` with a company slug (e.g. `accenture`) or a numeric LinkedIn company ID to look up a company. If you don't know the ID or slug, start with the slug — it is usually a lowercase version of the company name.
  </Accordion>
</AccordionGroup>
