Catch The Good Ones API
The Catch The Good Ones API is stream-centred. A stream is a campaign: a named operational unit that owns N(tracked_account, segment) pairs and a shared schedule + enrichment + delivery config. Three primary verbs frame the surface:
- Create streams with
POST /api/v2/streams(one-shot: handles + segments + everything) - Update streams with
PATCH /api/v2/streams/{id}(any setting, including full-replace pairs) - Extract leads with
GET /api/v2/streams/{id}/leads(per-stream) orGET /api/v2/leads(cross-stream polling)
Base URL
Quick start
- Generate an API key from your API Key page
- Verify the key:
- Create a campaign in one call:
- Pull leads from the campaign:
Endpoints by user goal
Set up a campaign
| Method | Endpoint | Purpose |
|---|---|---|
POST | /api/v2/streams | Create a campaign (one-shot: handles + segments + everything) |
POST | /api/v2/segments | Create a reusable segment to add to streams later |
GET | /api/v2/segments | List the segments you’ve authored |
GET | /api/v2/accounts | List your tracked accounts (active + sleeping) |
Manage campaigns
| Method | Endpoint | Purpose |
|---|---|---|
GET | /api/v2/streams | List your active campaigns |
GET | /api/v2/streams/{id} | Inspect a campaign |
PATCH | /api/v2/streams/{id} | Update any setting, including full-replace pairs |
DELETE | /api/v2/streams/{id} | Archive a campaign |
POST | /api/v2/streams/{id}/run | Trigger a sync across the campaign’s pairs |
POST | /api/v2/streams/{id}/re-test | Re-classify cached followers (optional {accountId?, segmentId?} scope) |
Monitor campaigns
| Method | Endpoint | Purpose |
|---|---|---|
GET | /api/v2/streams/{id}/runs | Sync history for one campaign |
GET | /api/v2/streams/{id}/runs/{runId} | Single run status + progress log |
GET | /api/v2/runs | Flat sync-run list across all campaigns |
Extract leads
| Method | Endpoint | Purpose |
|---|---|---|
GET | /api/v2/streams/{id}/leads | Per-campaign leads, with ?lifecycle, ?matchConfidence, ?accountId, ?segmentId, ?since, ?limit, ?offset. Pass ?summary=true for counts only. |
GET | /api/v2/leads | Cross-campaign poll. Supports ?streamId, ?since, ?lifecycle, ?groupBy=stream. |
POST | /api/v2/leads/{id}/feedback | Good / bad feedback (informs future classification) |
POST | /api/v2/leads/{id}/enrich | On-demand enrichment of one lead |
POST | /api/v2/leads/{id}/export | Mark a lead exported when you move it into your CRM |
Account management
| Method | Endpoint | Purpose |
|---|---|---|
GET | /api/v2/accounts | List tracked accounts |
POST | /api/v2/accounts/{id}/sleep | Sleep an account (decrements Stripe quantity) |
POST | /api/v2/accounts/{id}/wake | Wake a sleeping account |
POST | /api/v2/accounts/{id}/change-tier | Upgrade or downgrade an account’s tier |
Account + billing visibility
| Method | Endpoint | Purpose |
|---|---|---|
GET | /api/v2/me | Identity + per-account budgets + credit balance + totals rollup |
Webhooks
| Method | Endpoint | Purpose |
|---|---|---|
POST | /api/v2/webhooks/subscribe | Subscribe a webhook for real-time lead delivery. Filter: {streamId?, accountId?, sourceType?, feedbackStatus?, matchConfidence?} |
DELETE | /api/v2/webhooks/subscribe | Unsubscribe |
DM templates + notification settings
| Method | Endpoint | Purpose |
|---|---|---|
GET, POST | /api/v2/dm-templates | List / create canned DM templates |
GET, PUT, DELETE | /api/v2/dm-templates/{id} | Single-template CRUD |
GET, PUT | /api/v2/notification-settings | Team-default summary frequency + channels |
Lookups (Chrome extension surface)
One-shot enrichment + segment-from-description for the extension. Distinct from the campaign-centric surface above.| Method | Endpoint | Purpose |
|---|---|---|
POST | /api/v2/lookups/enrich | Look up LinkedIn URL + email for an X handle |
POST | /api/v2/lookups/enrich-email | Email-only lookup |
GET | /api/v2/lookups/enrich/history | Recent LinkedIn lookups |
GET | /api/v2/lookups/enrich-email/history | Recent email lookups |
POST | /api/v2/lookups/segments/from-description | Create a segment from a natural-language description |
DELETE | /api/v2/lookups/api-keys/{id} | Self-revoke (extension sign-out) |
Async operations
Some operations run asynchronously and return a run ID for polling:POST /api/v2/streams/{id}/runreturns{queued: [{accountId, syncRunId}], skipped: [{accountId, reason}]}. Poll each withGET /api/v2/streams/{id}/runs/{runId}.POST /api/v2/streams/{id}/re-testreturns the same shape. Poll the same way.
Billing effects
Several operations affect your Stripe subscription:POST /api/v2/streamswith new handles - upserts tracked accounts + increments Stripe quantity (response carriesbillingDeltaper account)PATCH /api/v2/streams/{id}with new handles inpairs- samePOST /api/v2/accounts/{id}/wake- increments Stripe quantityPOST /api/v2/accounts/{id}/sleep- decrements Stripe quantityPOST /api/v2/accounts/{id}/change-tier- upgrades apply immediately with proration; downgrades schedule for end-of-period
Rate limits
60 requests per minute per Bearer key. Response headers:| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per window (60) |
X-RateLimit-Remaining | Requests remaining in current window |
Retry-After | Seconds until the window resets (only on 429) |
Errors
Paywall and validation errors return a structured{ error: '<code>', message: '<copy>' } body. Branch on the code, not the message text. See the Migration guide for the full list.
Standard HTTP status codes apply:
| Status | Description |
|---|---|
200 | Success |
201 | Created |
400 | Invalid request (bad parameters or body) |
401 | Missing, invalid, or revoked API key |
403 | Forbidden (subscription required, budget exhausted, etc.) |
404 | Resource not found |
409 | Conflict (duplicate, concurrent operation) |
410 | Endpoint removed (see migration guide) |
422 | Unprocessable (e.g. private account) |
429 | Rate limit exceeded or credits exhausted |
502 | Upstream error (Stripe, etc.) |
503 | Service temporarily unavailable |