> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://gethookdai.crisp.help/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# 🔗 Public API

The Gethookd Public API lets you pull ad intelligence, competitor tracking data, saved collections, and AI-generated creatives directly into your own dashboards, reports, or internal tools — no browser needed.

Whether you're building an internal analytics pipeline, syncing ad data to a spreadsheet, or automating your creative workflow, the API gives you programmatic access to the same features you use in the Gethookd app.

---

## Before You Start

- **Plan required:** every annual plan (Starter, Pro, Team or Agency), or a monthly Team or Agency plan. Monthly Starter and Pro don't include API access.
- **Credits:** Reads cost **0.01 credits per item** returned. Writes vary by operation — some are free, most cost 1–5 credits. See **Credits & Billing** below for the full table.
- **Where to go:** Log in to Gethookd → **Integrations** → **API Keys**
- **Base URL:** `https://app.gethookd.ai/api/v1/`
- **Interactive docs:** [Scalar API Reference](https://registry.scalar.com/@gethookd/apis/gethookdai-api-documentation/latest) — try endpoints live with your token

---

## Step 1: Generate Your API Key

1. Go to **Integrations → API Keys**
2. Select the **scopes** your token needs from the dropdown. You can pick individual scopes (like "Explore Read" or "Brand Spy Write") or use **All Features (Read)** or **All Features (Full Access)** for broader access.
3. Click **Generate API Key**
4. Your new token appears in the table — click the **copy** button to copy it to your clipboard
5. **Important:** Store your token securely. You can reveal and copy it again later, but treat it like a password.

You can generate multiple keys with different scopes and revoke any key at any time.

---

## Step 2: Authenticate Your Requests

Every API request must include your token in the `Authorization` header:

```
Authorization: Bearer YOUR_API_TOKEN
```

**Test your token** by calling the auth check endpoint:

```
GET /api/v1/authcheck
```

A successful response looks like:

```json
{
  "errors": false,
  "data": {
    "authenticated": true,
    "workspace": {
      "id": 123,
      "name": "Your Workspace"
    },
    "scopes": ["explore:read"]
  }
}
```

If you see `"authenticated": true`, you're good to go.

---

## Endpoints

### Explore — Search the Ad Library

Search and filter across 21M+ ads, just like the Explore page in the app.

```
GET /api/v1/explore
```

**Scope required:** `explore:read`

**Query parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page, 1–100 (default: 20) |
| `query` | string | Free-text search (e.g., "supplements") |
| `sort_column` | string | Sort by: `created_at`, `start_date`, `days_active`, `used_count`, `popularity` |
| `sort_direction` | string | `asc` or `desc` (default: desc) |
| `start-date` | date | Start of date range (YYYY-MM-DD). Requires `end-date`. |
| `end-date` | date | End of date range (must be >= start-date) |
| `status` | string | `active` or `inactive` |
| `ad-format` | string | Comma-separated: `image`, `video`, `carousels`, `multi_images`, `multi_videos`, `dcos`, `dpas`, `events`, `page_likes`, `multi_medias` |
| `run-time` | integer | Minimum days active |
| `language` | string | Comma-separated 2-letter codes: `EN`, `ES`, `DE`, etc. |
| `platform` | string | Comma-separated: `facebook`, `instagram` |
| `niche` | string | Niche IDs (see below) |
| `performance_scores` | string | Comma-separated: `testing`, `scaling`, `growing`, `optimized`, `winning` |
| `used_count` | integer | Minimum creative usage count |
| `video_lengths` | string | `less_than_1_min`, `1_to_3_min`, `3_to_5_min`, `more_than_5_min` |
| `eu_transparency` | integer | `0` or `1` |
| `eu_total_reach` | integer | Minimum EU reach |
| `gender_audience` | string | `all`, `men`, `women` |
| `age_audience` | string | Age brackets: `13-17`, `18-24`, `25-34`, `35-44`, `45-54`, `55-64`, `65+` |
| `location` | string | 2-letter country codes: `US`, `DE`, `GB`, etc. |
| `ad_spend_range` | string | Spend bucket IDs (1–6) |
| `excluded_brands` | string | Brand IDs to exclude |
| `creative_categories` | string | Category IDs (see below) |
| `cta_types` | string | CTA types: `SHOP_NOW`, `LEARN_MORE`, `SIGN_UP`, `DOWNLOAD`, etc. |
| `active_ads_count` | integer | Minimum active ads per brand |
| `ads_per_brand_limit` | integer | Limit results per brand (1–50) |
| `min_ad_copy_length` | integer | Minimum character length of the ad copy (e.g. `1000` to target long-form ads) |
| `max_ad_copy_length` | integer | Maximum character length of the ad copy |
| `technologies` | string | Comma-separated tech slugs to filter by the landing-page tech stack (e.g. `shopify`, `klaviyo`) |
| `page_type` | string | Landing-page type slug(s) from the **Page Types** endpoint (e.g. PDP, Funnel, Listicle, Advertorial) |

**Niche IDs:** 1=Accessories, 2=Alcohol, 3=App/Software, 4=Automotive, 5=Beauty, 6=Book/Publishing, 7=Business/Professional, 8=Charity/NFP, 9=Info, 10=Entertainment, 11=Fashion, 12=Finance, 13=Food/Drink, 14=Games, 15=Government, 16=Health/Wellness, 17=Home/Garden, 18=Insurance, 19=Jewelry/Watches, 20=Kids/Baby, 21=Media/News, 22=Medical, 23=Pets, 24=Real Estate, 25=Service Business, 26=Sports/Outdoors, 27=Tech, 28=Travel, 29=Other, 30=Supplements

**Creative Category IDs:** 1=Before and After, 2=Testimonial/Reviews, 8=Promotion/Discount, 11=FAQ Explainers, 12=Holiday/Seasonal, 14=Humor/Fun, 16=Reasons Why, 17=Facts and Stats, 18=Features and Benefits, 19=Media and Press, 20=Us vs Them

**Performance Score Tiers (boundaries):** The `performance_score` field is a 0–100 number; the named tiers used by the `performance_scores` filter map as follows.

| Tier | Range |
|------|-------|
| `testing` | 1–40 |
| `scaling` | 41–60 |
| `growing` | 61–80 |
| `optimized` | 81–90 |
| `winning` | 91+ |

**Example request:**

```
GET /api/v1/explore?query=skincare&platform=facebook&status=active&per_page=10&sort_column=days_active&sort_direction=desc
```

**Example response:**

```json
{
  "errors": false,
  "data": [
    {
      "id": 123,
      "external_id": "9999999",
      "platform": "facebook, instagram",
      "display_format": "video",
      "title": "Great offer",
      "body": "...",
      "landing_page": "https://example.com",
      "cta_type": "SHOP_NOW",
      "cta_text": "Shop Now",
      "start_date": "2025-01-05",
      "end_date": null,
      "days_active": 21,
      "active_in_library": 1,
      "used_count": 4,
      "performance_score": 120,
      "performance_score_title": "Winning",
      "share_url": "https://app.gethookd.ai/share/ad/123...",
      "brand": {
        "external_id": "2016485295279615",
        "name": "Acme",
        "logo_url": "https://...",
        "active_ads": 109
      },
      "media": [
        {
          "type": "video",
          "url": "https://...",
          "thumbnail_url": "https://..."
        }
      ]
    }
  ],
  "used_credits": 0.10,
  "remaining_credits": 199.90,
  "sorting": { "column": "days_active", "direction": "desc" },
  "filters": { "platforms": ["facebook"] }
}
```

### Reading the Numbers in a Response

Any response that carries a count also tells you what was counted and when:

* `meta.count_basis_code` — what the number actually counts, so you never compare two numbers that measure different things.
* `meta.as_of` — when that number was measured.

When you filter by country, `meta.excluded_no_geo` tells you how many ads were left out because they carry no country data — so a smaller result set is explained rather than silently short.

Invalid values are refused up front instead of failing vaguely: a `geo` that isn't a two-letter country code, or a language we don't recognise, comes back as a validation error naming the parameter.

---

### Get a Single Ad

Look up one ad by its internal ID. Returns the same ad object you get from Explore — media, copy, performance score, and brand details.

**Scope required:** `explore:read` · **Cost:** free (no credits)

```
GET /api/v1/ads/{ad_id}
```

---

### Brands — Search the Catalog

Search Gethookd's full brand catalog, or look up one brand by ID. Handy for finding a brand's internal ID before adding it to Brand Spy.

**Scope required:** `brand-spy:read` · **Cost:** free (no credits)

#### Search brands

```
GET /api/v1/brands
```

| Parameter | Type | Description |
|---|---|---|
| `search` | string | Free-text match against the brand name |
| `parent_categories` | string | Niche / category IDs (comma-separated) |
| `sort_column` | string | `name`, `active_ads`, or `created_at` (default: `name`) |
| `sort_direction` | string | `asc` or `desc` |
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page, 1–100 (default: 20) |

#### Get a brand by ID

```
GET /api/v1/brands/{brand_id}
```

Returns the brand's name, logo, external ID, and active ad count.

---

### Page Types — Reference Data

Returns the list of active landing-page types (each with an `id`, `slug`, and `title`) — for example PDP, Funnel, Listicle, and Advertorial. Pass a `slug` to the `page_type` filter on the **Explore** endpoint to narrow results to ads pointing at that kind of page.

**Scope required:** any valid token · **Cost:** free (no credits)

```
GET /api/v1/page-types
```

---

### Brand Spy — Track Competitors

Monitor competitors' ad activity programmatically. List your spied brands, view their ads, add new brands, or remove them.

**Scope required:** `brand-spy:read` (for GET), `brand-spy:write` (for POST/DELETE)

#### List your spied brands

```
GET /api/v1/brandspy
```

| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page, 1–100 (default: 20) |
| `sort_column` | string | `created_at`, `active_ads`, `inactive_ads`, `last_spied_at` |
| `sort_direction` | string | `asc` or `desc` |

#### Get a brand's ads

```
GET /api/v1/brandspy/{brand_id}
```

| Parameter | Type | Description |
|-----------|------|-------------|
| `per_page` | integer | Ads per page, 1–100 (default: 20) |
| `status` | string | `active` or `inactive` |
| `platform` | string | Filter by platform: `facebook`, `instagram`, `tiktok`, etc. |

Returns the brand details plus a paginated list of their ads.

#### Add a brand to spy on

```
POST /api/v1/brandspy
```

**Body (JSON):**

```json
{ "brand_id": 12345 }
```

Returns the newly spied brand. If the brand is already being spied on, you'll get a `409 Conflict`.

#### Remove a spied brand

```
DELETE /api/v1/brandspy/{brand_id}
```

#### Get a brand's top-performing ads

```
GET /api/v1/brandspy/{brand_id}/top-ads
```

Returns a brand's currently-running ads, ranked by performance. `brand_id` accepts the brand's internal ID or its spied-brand record ID.

**Scope required:** `brand-spy:read` · **Cost:** free (no credits)

| Parameter | Type | Description |
|---|---|---|
| `limit` | integer | Number of ads to return, 1–50 (default: 10) |
| `platform` | string | Filter by platform: `facebook`, `instagram`, `tiktok`, etc. |

---

### Swipe File — Saved Ads

Access your saved ads collection. List, save, and remove ads from your swipe file.

**Scope required:** `swipe-file:read` (for GET), `swipe-file:write` (for POST/DELETE)

#### List saved ads

```
GET /api/v1/swipefile
```

| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page, 1–100 (default: 20) |
| `sort_column` | string | `created_at`, `start_date`, `days_active`, `used_count` |
| `sort_direction` | string | `asc` or `desc` |
| `creative_categories` | string | Comma-separated creative category IDs (same IDs as on Explore) |
| `tags` | string | Comma-separated tag IDs you've assigned to your saved ads |
| `languages` | string | Comma-separated 2-letter codes: `EN`, `ES`, `DE`, etc. |
| `platforms` | string | Comma-separated: `facebook`, `instagram`, `tiktok` |
| `performance_scores` | string | Comma-separated: `testing`, `scaling`, `growing`, `optimized`, `winning` |
| `video_lengths` | string | `less_than_1_min`, `1_to_3_min`, `3_to_5_min`, `more_than_5_min` |
| `display_formats` | string | Comma-separated: `image`, `video`, `carousel` |

These seven filters mirror the in-app Swipe File filter panel, so the API can now return the same subsets you'd see by ticking filters in the UI.

#### Save an ad

```
POST /api/v1/swipefile
```

**Body (JSON):**

```json
{ "ad_id": 12345 }
```

#### Remove a saved ad

```
DELETE /api/v1/swipefile/{ad_id}
```

---

### Boards — Organize Collections

Create and manage boards (folders) to organize ads into themed collections.

**Scope required:** `boards:read` (for GET), `boards:write` (for POST/PUT/DELETE)

#### List boards

```
GET /api/v1/boards
```

| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page, 1–100 (default: 20) |
| `sort_column` | string | `created_at`, `updated_at`, `name` |
| `sort_direction` | string | `asc` or `desc` |

#### Create a board

```
POST /api/v1/boards
```

**Body (JSON):**

```json
{ "name": "Q1 Winners", "description": "Top-performing ads from Q1" }
```

#### Get board details with ads

```
GET /api/v1/boards/{board_id}
```

#### Update a board

```
PUT /api/v1/boards/{board_id}
```

**Body (JSON):**

```json
{ "name": "Updated Name", "description": "Updated description" }
```

#### Delete a board

```
DELETE /api/v1/boards/{board_id}
```

#### Add an ad to a board

```
POST /api/v1/boards/{board_id}/ads
```

**Body (JSON):**

```json
{ "ad_id": 12345 }
```

#### Remove an ad from a board

```
DELETE /api/v1/boards/{board_id}/ads/{ad_id}
```

---

### Saved Searches — Reusable Explore Filters

Save the filter combinations you reach for most often (niche + creative category + languages + ad spend range, etc.) and reuse them programmatically. Saved Searches live on your workspace and can be created, listed, updated, and deleted entirely through the API.

**Scope required:** `searches:read` (for GET), `searches:write` (for POST/PUT/DELETE)

#### List saved searches

```
GET /api/v1/searches
```

| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page, 1–100 (default: 20) |

#### Create a saved search

```
POST /api/v1/searches
```

**Body (JSON):**

```json
{
  "name": "US Supplements — Winners",
  "parent_categories": [30],
  "creative_categories": [1, 2, 18],
  "languages": [1],
  "excluded_brands": [123, 456],
  "gender_audience": "all",
  "age_audience": "25-34,35-44",
  "ad_spend_range": "5,6",
  "ads_per_brand_limit": 4
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Display name, max 120 chars |
| `parent_categories` | array of integers | No | Niche IDs (see Niche IDs under Explore), max 50 |
| `creative_categories` | array of integers | No | Creative category IDs, max 50 |
| `languages` | array of integers | No | Internal language IDs, max 20 |
| `excluded_brands` | array of integers | No | Brand IDs to exclude, max 100 |
| `gender_audience` | string | No | `all`, `men`, or `women` |
| `age_audience` | string | No | Comma-separated age brackets (e.g. `25-34,35-44`) |
| `ad_spend_range` | string | No | Comma-separated spend bucket IDs (1–6) |
| `ads_per_brand_limit` | integer | No | Limit per brand, 1–50 |

If you try to create a saved search with a `name` you have already used in this workspace, the API returns a clear validation error instead of silently creating a duplicate.

#### Get a saved search

```
GET /api/v1/searches/{search_id}
```

Returns the saved-search record with the same fields you sent on create.

#### Update a saved search

```
PUT /api/v1/searches/{search_id}
```

Body uses the same shape as the create endpoint. Only fields you include are updated.

#### Delete a saved search

```
DELETE /api/v1/searches/{search_id}
```

A 403 (not 404) is returned if you try to access a saved search that belongs to a different user — by design, to avoid leaking IDs.

---

### Clone Ads — AI Ad Generation

Generate AI-powered ad variations based on existing ads, list your generation history, and retrieve results.

**Scope required:** `clone-ads:read` (for GET), `clone-ads:write` (for POST)

#### List clone history

```
GET /api/v1/clone-ads
```

| Parameter | Type | Description |
|-----------|------|-------------|
| `per_page` | integer | Results per page, 1–100 (default: 20) |
| `sort_direction` | string | `asc` or `desc` |

Each item in the response now includes:

* `variations_count` — how many variations the prompt requested
* `aspect_ratio` — `Square`, `Portrait`, or `Landscape`
* `model_slug` — which underlying model produced the generation
* `media[].is_product_reference` — `true` for the product image you provided, `false` for AI-generated outputs

This matches what you see on the Clone Ads history view in the app.

#### Generate cloned ad variations

```
POST /api/v1/clone-ads
```

**Body (JSON):**

```json
{
  "ad_id": 12345,
  "prompt": "Make it more playful and summer-themed",
  "aspect_ratio": "Square",
  "variations_count": 3
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `ad_id` | integer | Yes | The ad to use as inspiration |
| `prompt` | string | No | Custom instructions for the AI (max 4,000 chars) |
| `aspect_ratio` | string | No | `Square`, `Portrait`, or `Landscape` |
| `variations_count` | integer | No | Number of variations to generate, 1–10 (default: 3) |

**Note:** Generation is asynchronous. The response returns the job details immediately. Poll the detail endpoint to check when your images are ready.

#### Get clone details

```
GET /api/v1/clone-ads/{clone_id}
```

Returns the generation details including all generated image variations and their URLs.

---

## Credits & Billing

- **Cost:** 0.01 credits per item returned (per ad, per brand, per board)
- **When you're charged:** Only when data is successfully returned. Empty results cost nothing.
- **Writes:** the cost depends on what the call does. Several are free, and creating something new costs the most:

| Write operation | Credits |
| ---- |
| Save an ad to your swipe file, or remove one | Free |
| Stop spying on a brand | Free |
| Submit a support request | Free |
| Update a board | 1 |
| Delete a board, saved search, clone ad, brand profile or product | 1 |
| Remove an ad from a board | 1 |
| Start spying on a brand | 2 |
| Add an ad to a board | 2 |
| Update a saved search, brand profile or product | 2 |
| Create a board, saved search, brand profile or product | 5 |
| Generate a clone ad | 1 |

- **Clone Ads through the API cost 1 credit per generation**, however many variations you ask for. That is different from generating clone ads inside the app, where you pay 1–2 credits per variation depending on the model.
- **Every response includes** `used_credits` and `remaining_credits` so you can track your balance.

If you run out of credits mid-request, you'll receive:

```json
{
  "errors": true,
  "message": "Not enough credits",
  "data": {
    "feature": "public_api",
    "credits_needed": 0.16,
    "remaining_credits": "0.04",
    "feature_cost": 0.01
  }
}
```

**Status code:** `402 Payment Required`

---

## Rate Limits

To keep the API fast and fair for everyone, requests are limited per token:

| Window | Limit |
|--------|-------|
| Per second | 5 requests |
| Per minute | 300 requests |
| Per hour | 5,000 requests |

Every response includes rate limit headers so you know where you stand:

| Header | Description |
|--------|-------------|
| `X-RateLimit-Limit-Second` | Your per-second limit |
| `X-RateLimit-Remaining-Second` | Requests remaining this second |
| `X-RateLimit-Limit-Minute` | Your per-minute limit |
| `X-RateLimit-Remaining-Minute` | Requests remaining this minute |
| `X-RateLimit-Limit-Hour` | Your per-hour limit |
| `X-RateLimit-Remaining-Hour` | Requests remaining this hour |
| `Retry-After` | Seconds to wait (only on 429 responses) |

If you exceed a limit, you'll get a `429 Too Many Requests` response. Just wait for the `Retry-After` period and try again.

---

## Scopes Reference

Scopes control what each API token can access. When generating a token, you choose which scopes to grant.

| Scope | Allows |
|-------|--------|
| `explore:read` | Search and filter the ad library |
| `brand-spy:read` | List spied brands and view their ads |
| `brand-spy:write` | Add or remove spied brands |
| `swipe-file:read` | List saved ads |
| `swipe-file:write` | Save or remove ads from swipe file |
| `boards:read` | List and view boards |
| `boards:write` | Create, update, delete boards and manage ads in boards |
| `clone-ads:read` | List clone history and view results |
| `clone-ads:write` | Generate new cloned ad variations |
| `searches:read` | List and view saved searches |
| `searches:write` | Create, update, and delete saved searches |

**Shorthand scope names:** Token creation now also accepts the no-hyphen forms `swipefile:read`, `swipefile:write`, `brandspy:read`, and `brandspy:write`. They are stored as the canonical hyphenated form, so all downstream behavior is identical.

If a request requires a scope your token doesn't have, you'll get:

```json
{
  "errors": true,
  "message": "Forbidden. Missing scope: brand-spy:read"
}
```

**Status code:** `403 Forbidden`

---

## Error Handling

All error responses follow the same format:

```json
{
  "errors": true,
  "message": "Description of what went wrong"
}
```

| Status Code | Meaning |
|-------------|--------|
| `401` | Missing, invalid, or expired token |
| `402` | Not enough credits |
| `403` | Token is missing a required scope |
| `404` | Resource not found (e.g., brand or board doesn't exist) |
| `409` | Conflict (e.g., brand already being spied on) |
| `422` | Validation error (invalid parameters) |
| `429` | Rate limit exceeded — check `Retry-After` header |

---

## Troubleshooting

**"Unauthenticated" error**
Make sure your `Authorization` header starts with `Bearer ` (with a space) followed by your full token. Double-check that the token hasn't been revoked.

**"Not enough credits" on every request**
Check your remaining credits on your plan dashboard. You can purchase credit add-on packs or upgrade your plan for more credits.

**"Forbidden. Missing scope" error**
Your token doesn't have the right permissions for this endpoint. Generate a new token with the required scope.

**Empty results when filtering**
Try broadening your filters. Remove one filter at a time to identify which one is too restrictive. Make sure date ranges and niche/category IDs are valid.

**Rate limited (429 errors)**
Slow down your request rate. Check the `Retry-After` header and wait that many seconds before retrying. Consider adding a small delay between requests in your code.

---

## Workflow Ideas & Integration Tips

The API really shines when you connect it to other tools. Here are some ready-to-use workflows to get you started.

### 1. Competitor Strategy Brief (Zapier + Google Docs)

**Tools:** Zapier, Google Docs, Gethookd API

**How it works:**
1. Set a Zapier schedule trigger (e.g., every Monday morning)
2. Use the **Explore** endpoint to pull the top 20 active ads for a competitor's niche
3. Feed the ad copy and CTA data into a Google Doc template
4. Share the doc automatically with your team via Slack or email

**Great for:** Weekly competitive intelligence reports without lifting a finger.

---

### 2. Niche Trend Tracker (Make + Google Sheets)

**Tools:** Make (formerly Integromat), Google Sheets, Gethookd API

**How it works:**
1. Schedule a Make scenario to run daily
2. Call the **Explore** endpoint filtered by your niche (e.g., `niche=30` for Supplements) and sorted by `start_date desc`
3. Append new ads to a Google Sheet with columns: brand, headline, CTA, days active, performance score
4. Add a chart to visualize trends over time

**Great for:** Spotting emerging creative trends and seasonal patterns in your niche.

---

### 3. AI-Powered Copy Analysis (API + Claude or ChatGPT)

**Tools:** Any AI assistant (Claude, ChatGPT, etc.), Gethookd API

**How it works:**
1. Pull the top 50 active ads in your niche with `sort_column=days_active&sort_direction=desc`
2. Extract the `body` and `cta_type` fields from the response
3. Paste into your AI tool with a prompt like: *"Analyze these 50 ad copies. What are the top 5 hooks used? What CTAs convert best? Give me 3 new ad angles I haven't seen."*

**Great for:** Turning raw ad data into actionable creative strategy in minutes.

---

### 4. Auto-Save Winning Ads to Boards (Custom Script)

**Tools:** A simple script (Python, Node.js, etc.), Gethookd API

**How it works:**
1. Run a daily cron job that calls the **Explore** endpoint with `performance_scores=winning&status=active`
2. For each ad returned, call `POST /api/v1/boards/{board_id}/ads` to add it to your "Winners" board
3. Optional: check if the ad is already saved to avoid duplicates

```python
import requests

headers = {"Authorization": "Bearer YOUR_TOKEN"}

# Get winning ads
ads = requests.get(
    "https://app.gethookd.ai/api/v1/explore",
    params={"performance_scores": "winning", "status": "active", "per_page": 20},
    headers=headers
).json()["data"]

# Save to board
for ad in ads:
    requests.post(
        f"https://app.gethookd.ai/api/v1/boards/YOUR_BOARD_ID/ads",
        json={"ad_id": ad["id"]},
        headers=headers
    )
```

**Great for:** Building a curated collection of proven winners on autopilot.

---

### 5. Agency Client Reporting (Zapier + Notion or Airtable)

**Tools:** Zapier, Notion or Airtable, Gethookd API

**How it works:**
1. Use the **Brand Spy** endpoint to pull each client's competitor ads weekly
2. Push the data into a Notion database or Airtable base, one row per ad
3. Share a filtered view with each client showing only their competitors
4. Bonus: add a Zapier step to email the client a summary

**Great for:** Agencies who want to deliver ongoing competitive intelligence to clients without manual work.

---

### 6. Clone Ad Variations on Autopilot (Custom Script)

**Tools:** A script + Gethookd API

**How it works:**
1. Pull top-performing ads from Explore (e.g., `performance_scores=winning`)
2. For each ad, call `POST /api/v1/clone-ads` with a custom prompt (e.g., "Make it holiday-themed")
3. Poll `GET /api/v1/clone-ads/{clone_id}` until images are ready
4. Download the generated images or push them to your design tool

**Great for:** Quickly generating creative variations for A/B testing without a designer.

---

### Tips & Best Practices

| Tip | Why It Matters |
|-----|---------------|
| **Start with `authcheck`** | Always verify your token works before building a full workflow |
| **Use specific scopes** | Generate tokens with only the scopes each workflow needs — easier to revoke if compromised |
| **Add `per_page=1` for testing** | Saves credits while you're building and debugging your integration |
| **Cache responses locally** | Avoid burning credits by re-fetching the same data — cache results for at least a few hours |
| **Handle 429s gracefully** | Add retry logic with the `Retry-After` header value so your automation doesn't break |
| **Monitor `remaining_credits`** | Every response includes your balance — set up an alert when credits drop below a threshold |
| **Combine endpoints** | Use Explore to discover ads, then Boards to organize them, then Clone Ads to generate variations — one pipeline, three endpoints |

---

## FAQs

**Does using the API cost extra beyond my plan?**
No extra subscription cost — API access is included with every annual plan and with monthly Team and Agency. You pay with the same credits included in your plan. Each item returned costs 0.01 credits.

**Can I use the API on the Starter plan?**
Yes, on an annual Starter plan. Monthly Starter doesn't include API access — switch to annual billing, or move up to Team or Agency, from your account settings.

**I'm on a monthly Team or Agency plan. Do I have API access?**
Yes. API access is included on monthly Team and Agency — you don't need annual billing.

**Do I need an annual plan for API access?**
Only on Starter or Pro. Team and Agency include API access on monthly billing too.

**I'm on a free trial. Do I have API access?**
If you picked Team or Agency (monthly or annual), or any annual plan, yes — API access is part of that plan from the start.

**How do I revoke a compromised token?**
Go to **Integrations → API Keys**, find the token in the table, and click **Revoke**. The token stops working immediately. Then generate a new one.

**Can I create multiple API tokens?**
Yes! You can generate as many tokens as you need — for example, one per integration or team member. Each can be revoked independently.

**Is there a way to test the API without writing code?**
Yes — use the [interactive API docs](https://registry.scalar.com/@gethookd/apis/gethookdai-api-documentation/latest) where you can paste your token and try any endpoint directly in the browser.

**What format are dates in?**
All dates in requests and responses use `YYYY-MM-DD` format (e.g., `2025-06-15`).

**Can I use the API with AI tools like Claude Code or ChatGPT?**
Yes! Pull ad data from the Explore endpoint and feed it into your favourite AI tool to analyze competitor hooks, copy patterns, and CTAs across a niche. For example, you could pull the top 50 active skincare ads and ask AI to summarize the most common hooks and calls to action being used.

**Can I connect the API to Zapier or Make?**
Absolutely. Use the Explore endpoint as a data source in Zapier or Make to auto-export ads matching your filters to Google Sheets or Airtable on a schedule, send a Slack notification when you pull fresh ads for your niche, or feed ad data into any tool in your workflow.

**What can I build with custom scripts?**
Anything that benefits from fresh ad data on autopilot — internal dashboards that pull winning ads daily, automated competitor creative reports for agency clients, or scripts that track ad trends in your niche over time and flag new patterns.

---

## Related Articles

- [Credits System Explained](https://gethookd.crisp.help/en/article/credits-system-explained-1sbc488/)
- [Plans Overview](https://gethookd.crisp.help/en/article/plans-overview-choose-monthly-or-annual-1mhzbvn/)
- [Brand Spy](https://gethookd.crisp.help/en/article/brand-spy-jw5hnv/)
- [Clone Ads](https://gethookd.crisp.help/en/article/clone-ads-instantly-generate-high-converting-ad-creatives-1kzfvsu/)
- [Swipe File](https://gethookd.crisp.help/en/article/swipe-file-1mzp3s6/)


