# Zapier: start a search from a Google Sheet

Add a competitor's website to a sheet and RecruitAffiliates.ai starts a search for their affiliates.

Keep a Google Sheet of competitors. Each time you add a row, Zapier starts a competitor search in RecruitAffiliates.ai. A **competitor search** finds the people who already promote a rival product.

Each search uses one search credit. If it can't start, the credit comes back.

## What you need

- A plan that includes the API, and a key with the `finder:write` scope.
- A Google Sheet with a column called `Domain`, like `example.com`.
- A Zapier account. The request step uses "Webhooks by Zapier", which needs a paid Zapier plan.

## Build the Zap

1. In Zapier, create a Zap. For the trigger, pick "Google Sheets" and the event "New Spreadsheet Row". Point it at your sheet.
2. Add an action. Pick "Webhooks by Zapier" and the event "Custom Request".
3. Fill in the request like this:

| Setting | Value |
| --- | --- |
| Method | `POST` |
| URL | `https://api.affiliaterail.com/v1/finder/searches` |
| Data pass-through | False |
| Data | `{"type": "competitor", "seed": "{{Domain}}"}` |
| Unflatten | Yes |

4. Add three headers:

| Header | Value |
| --- | --- |
| `Authorization` | `Bearer rail_test_...` |
| `Content-Type` | `application/json` |
| `Idempotency-Key` | `sheet-row-{{Row ID}}` |

In the Data box, replace `{{Domain}}` with the Domain field from the trigger. In the header, replace `{{Row ID}}` with the row's id from the trigger.

5. Test the step. With a test key you get back a search in the `queued` state, and nothing is spent.
6. Swap the test key for a live key and turn the Zap on.

## Why the row id is in the key

An **idempotency key** is a unique string you send so a retried request never runs twice. Zapier retries a step when it times out. Using the row's id means a retry of the same row reuses the same key. You get the first search back instead of paying for a second one.

## Check on the search

A search takes a while to run. To see how it's going, add a later step with "Custom Request":

- Method: `GET`
- URL: `https://api.affiliaterail.com/v1/finder/searches/{{id}}`, using the `id` from step 3's answer
- Header: `Authorization: Bearer rail_...`

The new matches show up in the app, and in `GET /prospects`, when it's done.

## If something goes wrong

- A `402` means your plan doesn't include the API.
- A `429` means you've hit the rate limit. Zapier waits and retries on its own.
- Anything else: read `error.message` in the Zap's run history. It says what to fix.

Every rule for keys, errors and limits is in [the API guide](/api).

## Get events the moment they happen

The Zap above asks RecruitAffiliates.ai to do something. A webhook works the other way round: we tell Zapier the moment something happens, like a reply or a finished search. [Webhooks](/webhooks) explains the events. You need a plan that includes webhooks.

1. Start a Zap. For the trigger, pick "Webhooks by Zapier", then "Catch Raw Hook".
2. Copy the webhook URL Zapier shows you.
3. In RecruitAffiliates.ai, go to **Settings**, then the **Webhooks** tab. Add the URL as an endpoint and pick your events.
4. Press **Send a test**, then press "Test trigger" in Zapier to pull it in.

"Catch Raw Hook" keeps the raw body and headers, so a Code step can [check the signature](/webhooks#check-the-signature). "Catch Hook" reads the JSON for you, but then you can't check the signature.

Keep the URL private. Anyone who has it can post to your Zap. Checking the signature is what stops a fake.
