---
title: "Wyszukaj firmy i zapisz jako leady"
method: POST
path: "/leads/search"
tags: ["Leady"]
---

# Wyszukaj firmy i zapisz jako leady

`POST /leads/search`

## Request

- Base URL: `https://outreachpilot.pl/api/v1`
- URL: `https://outreachpilot.pl/api/v1/leads/search`
- Auth: HTTP bearer

Wyszukiwarka firm (Google Maps, PKT, OpenStreetMap, Panorama Firm) przez ten sam potok co aplikacja: dedupe, bramka jakości (miasto, kontakt, weryfikacja adresu) i ATOMOWE naliczenie limitu. Znalezione nowe firmy są zapisywane jako leady; te, które już masz, nie zużywają limitu. Zapytanie trwa zwykle 30-250 s, więc ustaw długi timeout klienta (min. 300 s). Kontakt w odpowiedzi (`email`, `phone`, `linkedin_url`, `email_status`, `email_verified_at`) jest dostępny w planie płatnym albo po podłączeniu skrzynki; bez nich pola są puste, a odpowiedź ma `contact_withheld: true`, `notice` i `links` (wyszukiwanie i zapis działają jak w aplikacji, leady da się dalej tagować i dodać do kampanii po ID). Wymaga zakresu `leads:scrape`.

**Wymagany zakres klucza:** `leads:scrape`.

## Request body

- object
  - `query` string, required: Branża lub fraza, np. `hydraulik`.
  - `city` string: Miasto, np. `Kraków`.
  - `sources` string[]: Źródła. Domyślnie wszystkie cztery.
  - `limit` integer: Ile firm maksymalnie (1-50). Przycinane do pozostałego limitu leadów.
  - `mode` 'auto' | 'no_website' | 'with_website': `no_website` = tylko firmy z potwierdzonym brakiem strony.
  - `require_email` boolean: Zapisuj tylko firmy z adresem e-mail.
  - `filter_has_phone` boolean: Tylko firmy z telefonem.
  - `filter_min_rating` number: Minimalna ocena w Google Maps (0-5).
  - `workspace_id` string: Klient agencji, do ktorego trafia zapis (ID z `GET /workspaces`, klient musi byc aktywny). Bez pola: "Moja firma".

## Response `200`

Sukces.

- object
  - `data` LeadSearchResult, required
    - `leads` object[], required: Nowo zapisane leady (bez tych, które już są w Twojej bazie).
      - `id` string, required
      - `email` string, nullable, required
      - `first_name` string, nullable, required
      - `last_name` string, nullable, required
      - `job_title` string, nullable, required
      - `phone` string, nullable, required
      - `linkedin_url` string, nullable, required
      - `company_name` string, nullable, required
      - `company_nip` string, nullable, required
      - `company_regon` string, nullable, required
      - `company_website` string, nullable, required
      - `company_city` string, nullable, required
      - `company_voivodeship` string, nullable, required
      - `company_address` string, nullable, required
      - `company_industry` string, nullable, required
      - `company_pkd` string, nullable, required
      - `company_country` string, nullable, required: ISO 3166-1 alpha-2; `null` = Polska.
      - `status` 'nowy' | 'w_kampanii' | 'odpowiedzial' | 'zainteresowany' | 'brak_zainteresowania' | 'odrzucony', required
      - `source` 'ceidg' | 'krs' | 'google_maps' | 'pkt' | 'firmy_net' | 'panorama' | 'osm' | 'linkedin' | 'import_csv' | 'manual', required
      - `tags` string[], required
      - `notes` string, nullable, required
      - `ai_score` integer, nullable, required: Ocena AI 1-10 albo `null`.
      - `email_status` 'valid' | 'risky' | 'invalid' | 'unknown', nullable, required: Wynik weryfikacji adresu (sonda SMTP): `valid` zweryfikowany, `risky` ryzykowny (catch-all), `invalid` nieprawidłowy, `unknown` nie udało się sprawdzić, `null` nie sprawdzono.
      - `email_verified_at` string, nullable, required: Data i czas ISO 8601 (UTC).
      - `website_status` 'has' | 'none_confirmed' | 'unknown', nullable, required
      - `registry_status` 'active' | 'suspended' | 'deleted' | 'liquidation' | 'bankrupt' | 'unknown', nullable, required: Status firmy w CEIDG/KRS.
      - `origin` object, nullable, required: Skąd i kiedy pozyskaliśmy dane (art. 14 RODO).
        - `source` string, required
        - `source_detail` string
        - `acquired_at` string, required: Data i czas ISO 8601 (UTC).
        - `source_url` string
      - `times_contacted` integer, required
      - `times_opened` integer, required
      - `times_clicked` integer, required
      - `times_replied` integer, required
      - `last_contacted_at` string, nullable, required: Data i czas ISO 8601 (UTC).
      - `created_at` string, required: Data i czas ISO 8601 (UTC).
      - `updated_at` string, required: Data i czas ISO 8601 (UTC).
    - `found` integer, required: Ile firm znaleziono w źródłach po filtrach.
    - `saved` integer, required
    - `already_owned` integer, required: Ile znalezionych firm było już w Twojej bazie (nie zużywają limitu).
    - `omitted_by_limit` integer, required
    - `limited_by` 'monthly' | 'daily', nullable, required
    - `remaining_quota` integer, required
    - `notes` string[], required: Uwagi (np. źródło chwilowo niedostępne).

## Other responses

- `400`: Nieprawidłowe żądanie. Kody: `invalid_request`.
- `401`: Brak, zły, odwołany lub wygasły klucz (`missing_api_key`, `invalid_api_key`, `api_key_revoked`, `api_key_expired`, `account_inactive`).
- `402`: Wyczerpany limit leadów. Kody: `lead_limit_reached`.
- `403`: Plan nie obejmuje API (`plan_upgrade_required`, odpowiedź zawiera informacje o planie; nie dotyczy tras wtyczki z kluczem `extension:*`) albo klucz nie ma wymaganego zakresu (`insufficient_scope`).
- `422`: Błąd walidacji. Kody: `validation_error`.
- `429`: Przekroczono limit żądań (`rate_limit_exceeded`). Zobacz nagłówek `Retry-After`.
- `503`: Usługa chwilowo niedostępna. Kody: `upstream_unavailable`.

---

[API](https://skmtc.dev/outreachpilot/apis/outreachpilot-api.md) · [All operations](https://skmtc.dev/outreachpilot/apis/outreachpilot-api/llms.txt) · [OpenAPI document](https://skmtc.dev/outreachpilot/apis/outreachpilot-api/revisions/2262dabfb07c?raw)
