# How do you track public tenders in a Google Sheet automatically?

> Source: https://www.rodz.io/en/guides/use-cases/public-tenders-to-google-sheets/
> Updated on 2026-10-12 · Peter Cools · Recipe · Public tenders · Google Sheets

## Short answer

Create a Public Tenders signal in Rodz with your keywords, French departments or countries and market types, then paste your Google Sheet URL in the signal’s Integrations tab. Every matching BOAMP or TED notice adds a row: buyer, subject, notice link, market type, response deadline and the published contact. A tender costs 7 credits.

## Key facts

- A delivered tender costs **7 credits**, plus 0.5 credit per email found when you turn on persona targeting and email finding.
- Two official sources: **BOAMP** for France and **TED** for European notices (`sources`: `boamp`, `ted`).
- Each notice is delivered **once**, within the signal’s daily limit.
- Rodz identifies **400,000+ signals a month** (July to September 2026 average).

Cost: 7 credits per tender

## Before you start

- A Rodz account with credits (the test account includes 100).
- A Google account with edit rights on the destination Google Sheet.
- Your business keywords (for example "IT maintenance", "cleaning services"), and if needed your French departments, CPV codes and market types.

## Steps

### 1. Connect Google Sheets to Rodz

In the Rodz dashboard, open **Integrations** and click **Google Sheets**. A Google window opens: pick the Google account and allow access. This connection is made once, in the dashboard (OAuth); it cannot be made with an API key.

### 2. Create the Public Tenders signal

In **My Signals**, click **Activate Signal** and pick the **Public Tenders** signal and set:

- the **sources**: `boamp` (French notices) and/or `ted` (European notices);
- the **keywords** searched in the tender subject (`keywords`) and excluded keywords (`keywordsExclude`);
- **French departments** (`departmentCodes`, for example `44`, `75`) for BOAMP, **countries** (`countryCodes`) and **CPV codes** (`cpvCodes`) for TED;
- the **market types** (`marketTypes`: Services, Fournitures, Travaux);
- the **minimum days before the deadline** (`minDaysUntilDeadline`), to drop notices that close too soon to answer.

Keywords match the subject as published, so use the notice’s language (French for BOAMP).

`Equivalent configuration (POST /api/v1/signals/public-tenders)`

```json
{
  "name": "IT maintenance tenders, western France",
  "status": "draft",
  "dailyLeadLimit": 20,
  "config": {
    "sources": ["boamp"],
    "keywords": ["maintenance informatique", "infogérance"],
    "keywordsExclude": ["travaux"],
    "departmentCodes": ["44", "35", "49"],
    "marketTypes": ["Services"],
    "minDaysUntilDeadline": 10
  }
}
```

### 3. Paste the Google Sheet URL in the signal

Create an empty Google Sheet (or a dedicated tab), copy its URL, then in the signal’s **Integrations** tab switch on **Google Sheets** and paste the URL. Through the API, it is a `PATCH` on the signal with the `googleSheets` destination.

Rodz writes the header row itself when the sheet is empty.

`Same setting through the API`

```bash
curl -X PATCH "https://api.rodz.io/api/v1/signals/$SIGNAL_ID" \
  -H "Authorization: Bearer $RODZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"destinations": {"googleSheets": {"sheetUrl": "https://docs.google.com/spreadsheets/d/YOUR_ID/edit"}}}'
```

### 4. Set the daily limit and activate

In **Basic Settings**, set the **Daily Lead Limit**: it caps how many notices are delivered, so it caps spend. Set the signal to **Active**. Each new matching notice adds a row to the sheet.

### 5. Sort and share the sheet

Add your own columns **to the right** of the Rodz columns (status, owner, bid / no bid): Rodz writes each value under the header of the same name and leaves columns it did not create alone. Sort on **Response Deadline** to see the notices that close first.

## Example payload

What Rodz delivers for one tender (webhook format, also returned by `GET /api/v1/signals/{signal_id}/leads`, without persona targeting). The sheet receives the main columns.

```json
{
  "signal": {
    "id": "d4f5a6b7-c8d9-4e0f-a1b2-c3d4e5f6a7b8",
    "name": "IT maintenance tenders, western France",
    "type": "public_tenders",
    "last_signal": "Public Tender",
    "last_signal_date": "2026-10-08",
    "job_offer_title": "Maintenance du parc informatique des services municipaux",
    "job_offer_url": "https://www.boamp.fr/avis/detail/26-000000",
    "matched_keywords": "maintenance informatique",
    "tender_description": "Maintenance préventive et curative du parc informatique, 3 lots.",
    "tender_deadline": "2026-11-06T12:00:00+00:00",
    "tender_published_date": "2026-10-07T02:00:00+00:00",
    "tender_cpv_code": "50320000",
    "tender_market_type": "services",
    "tender_nature": "cn-standard",
    "tender_submission_url": "https://tenders.example/file/123456",
    "tender_source": "boamp",
    "buyer_siren": "000000000",
    "buyer_city": "Nantes",
    "buyer_website": "https://city.example",
    "buyer_contact_email": "procurement@city.example",
    "buyer_contact_phone": "+33 2 00 00 00 00"
  },
  "company": {
    "name": "City of Example",
    "website": "https://city.example",
    "hq_country_code": "FR",
    "hq_city": "Nantes"
  }
}
```

## Sheet columns ← Rodz fields

| Google Sheets column                     | Rodz field (payload)                                              |
| ---------------------------------------- | ----------------------------------------------------------------- |
| Company                                  | `company.name` (the public buyer)                                 |
| Tender Subject                           | `signal.job_offer_title` (the notice subject)                     |
| Tender URL                               | `signal.job_offer_url` (link to the notice)                       |
| Market Type                              | `signal.tender_market_type`                                       |
| Response Deadline                        | `signal.tender_deadline`                                          |
| Tender Description                       | `signal.tender_description`                                       |
| Published Date                           | `signal.tender_published_date`                                    |
| CPV Code                                 | `signal.tender_cpv_code`                                          |
| Notice Source                            | `signal.tender_source`                                            |
| Buyer SIREN, Buyer City, Buyer Website   | `signal.buyer_siren`, `signal.buyer_city`, `signal.buyer_website` |
| Buyer Contact Email, Buyer Contact Phone | `signal.buyer_contact_email`, `signal.buyer_contact_phone`        |
| Signal Name                              | `signal.name`                                                     |

## Getting the keywords right

Keywords apply to the tender subject. A few simple rules:

1. **Start broad, then exclude**: three or four trade phrases, then exclusions (`keywordsExclude`) for the false positives you see.
2. **Use `minDaysUntilDeadline`**: a notice that closes in three days is rarely workable. Ten days is a common starting point.
3. **One signal per offer**: if you bid on different kinds of contracts, create one signal and one tab per offer, so each team has its sheet.

## Troubleshooting

- **No row arrives**: check that Google Sheets is switched on in the _signal’s_ Integrations tab, that the signal is Active and that the connected Google account can edit the sheet.
- **Empty values in a column**: the published notice does not carry the information (no deadline or no contact, for example).
- **Renamed column**: Rodz writes each value under the header of the same name; a renamed Rodz column is no longer recognized. Keep the original headers.

## Frequently asked questions

### Which columns does Rodz write to the sheet?

Among others: Timestamp, Company (the buyer), Tender Subject, Tender URL, Market Type, Response Deadline, Tender Description, Published Date, CPV Code, Notice Source, Buyer SIREN, Buyer City, Buyer Website, Buyer Contact Email, Buyer Contact Phone and Signal Name.

### Can I get European notices?

Yes. Add `ted` to the sources, then filter with `countryCodes` (2-letter ISO country codes) and `cpvCodes`. Departments and market types apply to BOAMP notices.

### Can the same notice arrive twice?

No: each tender is delivered once per signal, within the daily limit.

### Can I get a contact at the buyer?

The row already holds the email and phone published on the notice. For a named decision-maker, turn on persona targeting (`enablePersonaTargeting`, `targetPersonas`): the person found is delivered as the contact.

### What does it cost a month?

7 credits per delivered notice, capped by the daily limit. With a limit of 5 notices a day, the maximum is 35 credits a day. A credit costs €0.10 to €0.05 excl. VAT depending on the pack.

## Sources

- [BOAMP, the French official bulletin of public procurement notices](https://www.boamp.fr/)
- [TED, Tenders Electronic Daily (Official Journal of the European Union)](https://ted.europa.eu/)
- [Rodz API reference: Public Tenders signal, destinations](https://api.rodz.io/docs)
- [Google help: share files from Google Drive](https://support.google.com/docs/answer/2494822)

## Related guides

- https://www.rodz.io/en/guides/use-cases/job-offers-to-pipedrive/
- https://www.rodz.io/en/guides/api/poll-signal-leads/
- https://www.rodz.io/en/guides/api/webhook-receiver-hmac/
