# Adscan API — Complete Reference > Adscan is a competitive ad intelligence platform. Search, save, and analyze ads from Facebook, Instagram, LinkedIn, TikTok, and YouTube. Build AI-powered ad creatives with AdMachine. Collaborate with teams. --- ## Quick Start **Base URL:** `https://api.adscan.ai` **Authentication:** All authenticated endpoints require a Bearer token: ``` Authorization: Bearer adscan_live_xxxxxxxxxxxxxxxxxxxxx ``` **Protocol:** tRPC v11 over HTTP **Queries (GET):** ``` GET https://api.adscan.ai/.?input={"json":{...}} Authorization: Bearer adscan_live_xxx ``` **Mutations (POST):** ``` POST https://api.adscan.ai/. Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{...}} ``` **Batch calls** — comma-separated procedure names: ``` GET https://api.adscan.ai/ads.list,boards.list?batch=1&input={"0":{"json":{"limit":5}},"1":{"json":{}}} ``` **Important:** The `{"json": {...}}` wrapper is required for ALL endpoints — `ads.*`, `brandSpy.*`, `boards.*`, etc. This is the standard tRPC v11 wire format. **Response envelope:** All successful responses are wrapped: ```json { "result": { "data": { "json": { ... } } } } ``` --- ## Non-tRPC Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | GET | `/health` | no | Health check, returns `{"ok":true}` | | GET | `/llms.txt` | no | This file | --- ## Complete Procedure Index ### Ad Intelligence (Core) | Procedure | Type | Auth | Description | |-----------|------|------|-------------| | `ping` | query | no | Health check, returns latest ad title | | `ads.list` | query | yes | Search and filter your saved ads (only returns ads saved to your boards — use brandSpy for discovery) | | `ads.getDetails` | query | yes | Get full ad details by ID or hash | | `ads.getViewStats` | query | yes | Get historical view stats for an ad | | `ads.getFilterValues` | query | yes | Get available filter options (ad types, languages) | | `ads.listTopCompanies` | query | yes | Search advertisers by name (use to find exact company name for brandSpy queries) | | `ads.listBoardsContaining` | query | yes | Get boards containing a specific ad | | `ads.listBoardsContainingBatch` | query | yes | Batch: get boards for multiple ads | | `ads.getRecentKeywords` | query | yes | Get recent search history | | `ads.addToBoard` | mutation | yes | Save an ad to a board | | `ads.removeFromBoard` | mutation | yes | Remove an ad from a board | | `ads.saveFromExtension` | mutation | yes | Save ad from browser extension | | `ads.saveTranscription` | mutation | yes | Save video ad transcription | | `ads.delete` | mutation | admin | Delete an ad (admin only) | | `ads.saveRecentKeyword` | mutation | yes | Save a recent search keyword | | `ads.removeRecentKeyword` | mutation | yes | Remove a recent keyword | ### Boards (Collections) | Procedure | Type | Auth | Description | |-----------|------|------|-------------| | `boards.list` | query | yes | List all user's boards (personal + team) | | `boards.create` | mutation | yes | Create a new board | | `boards.update` | mutation | yes | Rename a board | | `boards.remove` | mutation | yes | Delete a board | | `boards.updateSlug` | mutation | yes | Change board's public URL slug | | `boards.updateDescription` | mutation | yes | Update board description | | `boards.togglePublic` | mutation | yes | Make board public or private | | `boards.checkSlugAvailability` | query | no | Check if a slug is available | | `boards.convertToTeam` | mutation | yes | Convert personal board to team board | ### Brand Spy (Ad Discovery & Competitor Intelligence) These are the endpoints for discovering ads and researching competitors across the full AdScan database. **Company name matching is case-insensitive but must match the stored name** — use `ads.listTopCompanies` to look up the correct name (e.g. search "madgicx" to find "madgicx.com"). | Procedure | Type | Auth | Description | |-----------|------|------|-------------| | `brandSpy.listTopAdvertisers` | query | yes | Discover top advertisers globally ranked by reach (no companyName needed) | | `brandSpy.getOverview` | query | yes | Full competitor overview: stats, demographics, media breakdown | | `brandSpy.getAdCopies` | query | yes | Ranked ad copy texts with performance scores, reach, and run duration | | `brandSpy.getHeadlines` | query | yes | Ranked headlines with performance scores (same schema as getAdCopies) | | `brandSpy.getLandingPages` | query | yes | Landing page distribution — which URLs a competitor drives traffic to | | `brandSpy.getTimeline` | query | yes | Ad launch timeline with thumbnails | | `brandSpy.listSimilarAdvertisers` | query | yes | Brands similar to a given brand ("More brands like X"), by ad-embedding similarity (shared Facebook page categories as fallback) | ### Companies (Following) | Procedure | Type | Auth | Description | |-----------|------|------|-------------| | `companies.follow` | mutation | yes | Follow a company | | `companies.unfollow` | mutation | yes | Unfollow a company | | `companies.listFollowed` | query | yes | List all followed companies | | `companies.isFollowing` | query | yes | Check if following a company | ### Teams (Collaboration) | Procedure | Type | Auth | Description | |-----------|------|------|-------------| | `teams.create` | mutation | yes | Create a team | | `teams.get` | query | yes | Get team details with members | | `teams.list` | query | yes | List user's teams | | `teams.update` | mutation | yes | Update team name/description | | `teams.delete` | mutation | yes | Delete a team (owner only) | | `teams.leave` | mutation | yes | Leave a team | | `teams.listMembers` | query | yes | List team members | | `teams.inviteByEmail` | mutation | yes | Invite member by email | | `teams.acceptInvite` | mutation | yes | Accept team invitation | | `teams.removeMember` | mutation | yes | Remove a team member | | `teams.updateRole` | mutation | yes | Update member's role | | `teams.getActivity` | query | yes | Get team activity log | | `teams.getStats` | query | yes | Get team statistics | | `teams.regenerateInviteCode` | mutation | yes | Regenerate invite link | | `teams.listPendingInvites` | query | yes | List pending invitations | | `teams.cancelInvite` | mutation | yes | Cancel a pending invite | | `teams.validateInviteCode` | query | no | Validate an invite code | | `teams.joinTeam` | mutation | yes | Join team via invite code | | `teams.migrateData` | mutation | yes | Migrate personal data to team | ### Auth & API Keys | Procedure | Type | Auth | Description | |-----------|------|------|-------------| | `auth.me` | query | no | Get current user info | | `auth.updateName` | mutation | yes | Update display name | | `auth.updateInstagramUsername` | mutation | yes | Update Instagram username | | `apiKeys.create` | mutation | yes | Create an API key | | `apiKeys.list` | query | yes | List all API keys | | `apiKeys.revoke` | mutation | yes | Revoke an API key | ### Public (No Auth Required) | Procedure | Type | Auth | Description | |-----------|------|------|-------------| | `publicAds.list` | query | no | Public ad search | | `publicAds.listLinkedIn` | query | no | Public LinkedIn ad search | | `publicBoards.get` | query | no | Get a public board by slug | | `publicBoards.listAds` | query | no | List ads in a public board | | `publicBoards.listAll` | query | no | List all public boards | ### AdMachine (AI Ad Creation) | Procedure | Type | Auth | Description | |-----------|------|------|-------------| | `admachine.me` | query | yes | Get user session with teams | | `admachine.analyzeDomain` | query | no | Analyze a business domain with AI | | `admachine.matchCompetitors` | query | no | Match competitor names to database | | `admachine.searchAdvertisers` | query | no | Autocomplete advertiser search | | `admachine.loadTopAds` | query | no | Load top ads for given companies | | `admachine.generateImage` | mutation | yes | Generate ad image with AI | | `admachine.generateCopy` | mutation | yes | Generate ad copy with AI | | `admachine.createTeam` | mutation | yes | Create an AdMachine team | | `admachine.getMyTeams` | query | yes | List user's AdMachine teams | | `admachine.updateTeam` | mutation | yes | Update AdMachine team | | `admachine.inviteMember` | mutation | yes | Invite to AdMachine team | | `admachine.joinTeam` | mutation | yes | Join AdMachine team | | `admachine.removeMember` | mutation | yes | Remove from AdMachine team | | `admachine.createProject` | mutation | yes | Create a project | | `admachine.getProject` | query | yes | Get project details | | `admachine.listProjects` | query | yes | List projects in a team | | `admachine.updateProject` | mutation | yes | Update project settings | | `admachine.deleteProject` | mutation | yes | Delete a project | | `admachine.addCompetitor` | mutation | yes | Add competitor to project | | `admachine.removeCompetitor` | mutation | yes | Remove competitor from project | | `admachine.addCards` | mutation | yes | Add cards to project board | | `admachine.moveCard` | mutation | yes | Move card between columns | | `admachine.updateCard` | mutation | yes | Update card content | | `admachine.removeCard` | mutation | yes | Remove a card | | `admachine.getCards` | query | yes | Get all cards in a project | | `admachine.clearColumn` | mutation | yes | Clear all cards in a column | | `admachine.getActivityLog` | query | yes | Get project activity log | ### Image Storage | Procedure | Type | Auth | Description | |-----------|------|------|-------------| | `aiImages.list` | query | yes | List user's AI-generated images | | `aiImages.delete` | mutation | yes | Delete an AI image | | `brandImages.list` | query | yes | List user's brand images | | `brandImages.delete` | mutation | yes | Delete a brand image | --- ## Detailed Procedure Reference --- ### ping Health check. Returns the title of the latest ad in the database. **Type:** query | **Auth:** none **Input:** none **Example request:** ``` GET /ping ``` **Example response:** ```json { "result": { "data": { "json": "Summer Sale - 50% Off Everything" } } } ``` --- ### ads.list Search and filter your **saved** ads (ads you've previously saved to boards via the Chrome extension or `ads.addToBoard`). This endpoint does NOT discover new ads — use `brandSpy.*` endpoints for ad discovery and competitor research. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | cursor | number | no | — | Pagination cursor (ad ID from previous page's `nextCursor`) | | limit | number | no | 20 | Results per page (max varies) | | searchQuery | string | no | — | Full-text search across advertiser name and ad content | | boardId | number or "ALL" | no | — | Filter to ads in a specific board, or "ALL" for any saved ad | | languages | string[] | no | — | Filter by language codes (e.g. ["en", "fr"]) | | adTypes | string[] | no | — | Filter by advertiser industry/category | | companyNames | string[] or "FOLLOWED" | no | — | Filter by company names, or "FOLLOWED" for followed companies | | ctaTypes | string[] | no | — | Filter by CTA button text (e.g. ["Shop Now", "Learn More"]) | | platforms | string[] | no | — | "facebook", "instagram", "youtube", "linkedin", "tiktok" | | formats | string[] | no | — | "video", "image", "carousel", "dco", "dpa", "other" | | isPartnership | boolean | no | — | Filter partnership/branded content ads only | | viewsMin | number | no | — | Minimum engagement views | | viewsMax | number | no | — | Maximum engagement views | | dateFrom | string | no | — | ISO date string (e.g. "2025-01-01") | | dateTo | string | no | — | ISO date string (e.g. "2025-12-31") | | sortBy | string | no | "date" | "date", "views", "likes", "comments" | **Example request:** ``` GET /ads.list?input={"json":{"limit":2,"platforms":["facebook"],"sortBy":"views","viewsMin":10000}} ``` **Example response:** ```json { "result": { "data": { "json": { "ads": [ { "id": 12345, "platform": "facebook", "displayFormat": "image", "isPublished": true, "isActive": true, "language": "en", "startDate": "2025-06-01T00:00:00.000Z", "endDate": null, "sourceUrl": "https://facebook.com/ads/library/?id=123", "createdAt": "2025-06-15T10:30:00.000Z", "advertiser": { "name": "Nike", "profilePicUrl": "https://media.adscan.ai/logos/nike.jpg" }, "partner": null, "cards": [ { "position": 0, "title": "Just Do It", "body": "Step into greatness with our new collection.", "caption": null, "mediaUrl": "https://media.adscan.ai/ads/12345_0.jpg", "mediaType": "image", "thumbnailUrl": null, "videoLengthSeconds": null, "ctaText": "Shop Now", "linkUrl": "https://nike.com/new", "linkDescription": "Nike.com" } ], "engagement": { "reach": 500000, "views": 250000, "impressions": 750000, "likes": 12000, "comments": 340 } } ], "nextCursor": 12344, "hasMore": true } } } } ``` **Pagination:** Pass `nextCursor` as `cursor` in the next request to get the next page. When `hasMore` is false, there are no more results. --- ### ads.getDetails Get full details for a single ad by internal ID or platform-specific hash. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | id | number | no | Internal ad ID | | hash | string | no | Platform-specific hash (Facebook/Instagram/LinkedIn/YouTube) | One of `id` or `hash` must be provided. **Example request:** ``` GET /ads.getDetails?input={"json":{"id":12345}} ``` **Example response:** ```json { "result": { "data": { "json": { "id": 12345, "platform": "facebook", "displayFormat": "image", "isPublished": true, "isActive": true, "language": "en", "startDate": "2025-06-01T00:00:00.000Z", "endDate": null, "sourceUrl": "https://facebook.com/ads/library/?id=123", "createdAt": "2025-06-15T10:30:00.000Z", "advertiser": { "name": "Nike", "profilePicUrl": "https://media.adscan.ai/logos/nike.jpg" }, "partner": null, "cards": [ { "position": 0, "title": "Just Do It", "body": "Step into greatness with our new collection.", "caption": null, "mediaUrl": "https://media.adscan.ai/ads/12345_0.jpg", "mediaType": "image", "thumbnailUrl": null, "videoLengthSeconds": null, "ctaText": "Shop Now", "linkUrl": "https://nike.com/new", "linkDescription": "Nike.com" } ], "engagement": { "reach": 500000, "views": 250000, "impressions": 750000, "likes": 12000, "comments": 340 }, "engagementHistory": [ { "date": "2025-06-10T00:00:00.000Z", "views": 50000 }, { "date": "2025-06-15T00:00:00.000Z", "views": 250000 } ], "demographics": { "gender": { "male": 0.45, "female": 0.55 }, "country": { "US": 0.6, "UK": 0.2, "CA": 0.1 }, "age": { "18-24": 0.3, "25-34": 0.4, "35-44": 0.2 } } } } } } ``` --- ### ads.getViewStats Get historical daily view/engagement stats for an ad over time. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | adId | number | yes | **Example request:** ``` GET /ads.getViewStats?input={"json":{"adId":12345}} ``` **Example response:** ```json { "result": { "data": { "json": [ { "date": "2025-06-01T00:00:00.000Z", "views": 1200 }, { "date": "2025-06-02T00:00:00.000Z", "views": 3400 }, { "date": "2025-06-03T00:00:00.000Z", "views": 5600 }, { "date": "2025-06-04T00:00:00.000Z", "views": 12000 } ] } } } ``` --- ### ads.getFilterValues Get available filter values (advertiser categories and languages) for the current dataset. Optionally scope to a board. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | boardId | number | no | Scope filter values to a specific board | **Example request:** ``` GET /ads.getFilterValues?input={"json":{}} ``` **Example response:** ```json { "result": { "data": { "json": { "adTypes": ["E-Commerce", "SaaS", "Finance", "Health", "Education", "Entertainment"], "languages": ["en", "fr", "de", "es", "pt", "it", "nl", "ja", "ko", "zh"] } } } } ``` --- ### ads.listTopCompanies Search for companies/advertisers by name. Returns top 4 matches with logo and ad count. **Use this to find the exact company name before calling `brandSpy.*` endpoints** — company name matching in Brand Spy must match the stored name (e.g. `"madgicx.com"` not `"Madgicx"`). **Type:** query | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | name | string | yes | **Example request:** ``` GET /ads.listTopCompanies?input={"json":{"name":"nike"}} ``` **Example response:** ```json { "result": { "data": { "json": { "companies": [ { "name": "Nike", "brandLogo": "https://media.adscan.ai/logos/nike.jpg", "adCount": 2340 }, { "name": "Nike Football", "brandLogo": "https://media.adscan.ai/logos/nikefb.jpg", "adCount": 456 }, { "name": "Nike Running", "brandLogo": "https://media.adscan.ai/logos/nikerun.jpg", "adCount": 189 }, { "name": "Nike Basketball", "brandLogo": "https://media.adscan.ai/logos/nikebb.jpg", "adCount": 95 } ] } } } } ``` --- ### ads.listBoardsContaining Get which of the user's boards contain a specific ad. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | adId | number | yes | **Example request:** ``` GET /ads.listBoardsContaining?input={"json":{"adId":12345}} ``` **Example response:** ```json { "result": { "data": { "json": { "boardIds": [1, 5, 12] } } } } ``` --- ### ads.listBoardsContainingBatch Batch version: get boards for multiple ads at once. Returns a map of ad IDs to board ID arrays. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | adIds | number[] | yes | **Example request:** ``` GET /ads.listBoardsContainingBatch?input={"json":{"adIds":[12345,12346,12347]}} ``` **Example response:** ```json { "result": { "data": { "json": { "12345": [1, 5], "12346": [1], "12347": [] } } } } ``` --- ### ads.getRecentKeywords Get the user's recent search history (keywords and company searches). Stored in Redis, max 8 items. **Type:** query | **Auth:** required **Input:** none **Example request:** ``` GET /ads.getRecentKeywords ``` **Example response:** ```json { "result": { "data": { "json": { "items": [ { "type": "keyword", "value": "running shoes" }, { "type": "company", "name": "Nike", "logo": "https://media.adscan.ai/logos/nike.jpg", "adCount": 2340 }, { "type": "keyword", "value": "summer sale" } ], "keywords": ["running shoes", "summer sale"] } } } } ``` --- ### ads.addToBoard Save an ad to a board (swipe library collection). **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | adId | number | yes | | boardId | number | yes | **Example request:** ``` POST /ads.addToBoard Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"adId":12345,"boardId":1}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### ads.removeFromBoard Remove an ad from a board. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | adId | number | yes | | boardId | number | yes | **Example request:** ``` POST /ads.removeFromBoard Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"adId":12345,"boardId":1}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### ads.saveFromExtension Save an ad discovered via the Adscan browser extension. Creates or updates the ad record and links it to a board. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | boardId | number | yes | Board to save to | | adId | string | yes | External platform ad ID | | adAdvertiserName | string | no | Advertiser name | | adBodyText | string | no | Ad body text | | adMediaUrl | string | no | Media URL (image or video) | | adMediaType | "image" or "video" | no | Media type | | sourcePlatform | string | yes | "facebook", "tiktok-creative", "tiktok-library", or "linkedin" | | sourceUrl | string | no | Source page URL | | impressionRank | number | no | Impression ranking position | | impressionRankTotal | number | no | Total ads in ranking | | rankCountry | string | no | Country code for ranking | **Example request:** ``` POST /ads.saveFromExtension Content-Type: application/json Authorization: Bearer adscan_live_xxx { "json": { "boardId": 1, "adId": "fb_123456789", "adAdvertiserName": "Nike", "adBodyText": "Just Do It. New collection available now.", "adMediaUrl": "https://scontent.facebook.com/v/image.jpg", "adMediaType": "image", "sourcePlatform": "facebook", "sourceUrl": "https://facebook.com/ads/library/?id=123456789" } } ``` **Example response:** ```json { "result": { "data": { "json": { "success": true, "alreadyExists": false, "url": "https://adscan.ai/ad/12345" } } } } ``` --- ### ads.saveTranscription Save a transcription for a video ad card. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Default | |-------|------|----------|---------| | adId | number | yes | — | | cardPosition | number | no | 0 | | transcription | string | yes | — | **Example request:** ``` POST /ads.saveTranscription Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"adId":12345,"cardPosition":0,"transcription":"Welcome to our summer collection..."}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### ads.delete Delete an ad. Restricted to admin accounts (@adscan.ai emails only). **Type:** mutation | **Auth:** admin only **Input:** | Field | Type | Required | |-------|------|----------| | adId | number | yes | **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### ads.saveRecentKeyword Save a recent search keyword or company to the user's search history (stored in Redis, max 8 items). **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | keyword | string | no | Text keyword to save | | companyName | string | no | Company name to save | | companyLogo | string | no | Company logo URL (when saving company) | | companyAdCount | number | no | Company ad count (when saving company) | Provide either `keyword` OR `companyName`+`companyLogo`+`companyAdCount`. **Example request:** ``` POST /ads.saveRecentKeyword Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"keyword":"running shoes"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### ads.removeRecentKeyword Remove a keyword or company from the user's search history. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | keyword | string | no | | companyName | string | no | **Example request:** ``` POST /ads.removeRecentKeyword Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"keyword":"running shoes"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### boards.list List all boards for the current user, including personal and team boards. Returns hierarchical structure with nested children. **Type:** query | **Auth:** required **Input:** none **Example request:** ``` GET /boards.list ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": 1, "name": "Inspiration", "slug": "inspiration", "description": "My favorite ad designs", "parentId": null, "teamId": null, "isTeamBoard": false, "isPublic": false, "ownerId": "user_abc", "ownerName": "John Doe", "canEdit": true, "canDelete": true, "children": [ { "id": 2, "name": "Facebook Ads", "slug": "facebook-ads", "description": null, "parentId": 1, "teamId": null, "isTeamBoard": false, "isPublic": false, "children": [] } ] }, { "id": 10, "name": "Team Board", "slug": "team-board", "description": "Shared with team", "parentId": null, "teamId": 3, "isTeamBoard": true, "isPublic": true, "children": [] } ] } } } ``` --- ### boards.create Create a new board. Optionally nest under a parent board or assign to a team. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | name | string | yes | Board name | | parentId | number | no | Parent board ID for nesting | | teamId | number | no | Team ID to create as team board | **Example request:** ``` POST /boards.create Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"name":"Competitors","parentId":1}} ``` **Example response:** ```json { "result": { "data": { "json": { "id": 5, "name": "Competitors", "slug": "competitors", "parentId": 1, "teamId": null, "isTeamBoard": false } } } } ``` --- ### boards.update Rename a board. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | id | number | yes | | name | string | yes | **Example request:** ``` POST /boards.update Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":5,"name":"Top Competitors"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true, "id": 5, "name": "Top Competitors" } } } } ``` --- ### boards.remove Delete a board and disassociate all ads from it. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | id | number | yes | **Example request:** ``` POST /boards.remove Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":5}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### boards.updateSlug Change a board's public URL slug. Must be unique across all boards. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | id | number | yes | Board ID | | slug | string | yes | 3-191 chars, lowercase alphanumeric + hyphens | **Example request:** ``` POST /boards.updateSlug Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":5,"slug":"top-competitors-2025"}} ``` **Example response:** ```json { "result": { "data": { "json": { "slug": "top-competitors-2025" } } } } ``` --- ### boards.updateDescription Update a board's description. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | id | number | yes | | description | string or null | yes | **Example request:** ``` POST /boards.updateDescription Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":5,"description":"Collection of competitor Facebook ads from Q1 2025"}} ``` **Example response:** ```json { "result": { "data": { "json": { "description": "Collection of competitor Facebook ads from Q1 2025" } } } } ``` --- ### boards.togglePublic Make a board public (shareable via URL at adscan.ai/boards/{slug}) or private. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | id | number | yes | | isPublic | boolean | yes | **Example request:** ``` POST /boards.togglePublic Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":5,"isPublic":true}} ``` **Example response:** ```json { "result": { "data": { "json": { "isPublic": true } } } } ``` --- ### boards.checkSlugAvailability Check if a public board slug is available. No auth required. **Type:** query | **Auth:** none **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | slug | string | yes | Slug to check | | excludeBoardId | number | no | Exclude a board from the check (for editing existing slugs) | **Example request:** ``` GET /boards.checkSlugAvailability?input={"json":{"slug":"my-board"}} ``` **Example response:** ```json { "result": { "data": { "json": { "available": true, "isValidFormat": true, "message": "This slug is available" } } } } ``` --- ### boards.convertToTeam Convert a personal board into a team board. Board owner only. **Type:** mutation | **Auth:** required (board owner) **Input:** | Field | Type | Required | |-------|------|----------| | boardId | number | yes | | teamId | number | yes | **Example request:** ``` POST /boards.convertToTeam Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"boardId":5,"teamId":3}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### brandSpy.getOverview Get a comprehensive competitive overview for a company: total stats, demographics, and media breakdown. For landing pages use `brandSpy.getLandingPages`; for the brand's top ads use `ads.list` with `companyNames` + `sortBy: "views"`. **Important:** `companyName` must match the stored name — use `ads.listTopCompanies` to look it up first. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | companyName | string | yes | — | Advertiser name (exact match) | | dateFrom | string | no | — | ISO date filter start | | dateTo | string | no | — | ISO date filter end | | status | string | no | "all" | "active", "inactive", or "all" | | mediaType | string | no | "all" | "image", "video", or "all" | | language | string | no | — | Language code filter | **Example request:** ``` GET /brandSpy.getOverview?input={"json":{"companyName":"Nike","status":"active"}} ``` **Example response:** ```json { "result": { "data": { "json": { "advertiserId": 100, "brandName": "Nike", "brandLogo": "https://media.adscan.ai/logos/nike.jpg", "pageId": "123456", "stats": { "totalAds": 2340, "activeAds": 890, "inactiveAds": 1450, "totalReach": 50000000, "totalSpend": 0 }, "mediaTypeBreakdown": { "image": 1200, "video": 900, "carousel": 240 }, "demographics": { "gender": { "male": 0.45, "female": 0.55 }, "country": [ { "code": "US", "percentage": 0.6 }, { "code": "UK", "percentage": 0.2 } ], "age": [ { "range": "18-24", "percentage": 0.3 }, { "range": "25-34", "percentage": 0.4 } ] }, "activeAdsOverTime": [ { "date": "2025-01-01", "count": 120 }, { "date": "2025-02-01", "count": 145 } ] } } } } ``` --- ### brandSpy.getAdCopies Get analysis of a company's ad copy texts, sorted by performance. Includes deduplication and performance scoring. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | companyName | string | yes | — | Advertiser name | | cursor | number | no | — | Pagination cursor | | limit | number | no | 10 | Results per page | | dateFrom | string | no | — | ISO date filter start | | dateTo | string | no | — | ISO date filter end | | status | string | no | "all" | "active", "inactive", or "all" | | mediaType | string | no | "all" | "image", "video", or "all" | | language | string | no | — | Language code filter | | sortBy | string | no | "performanceScore" | "adCount", "reach", "longestRunning", "performanceScore" | **Example request:** ``` GET /brandSpy.getAdCopies?input={"json":{"companyName":"Nike","sortBy":"reach","limit":5}} ``` **Example response:** ```json { "result": { "data": { "json": { "copies": [ { "text": "Step into greatness. Our new collection is here.", "adCount": 5, "totalReach": 2500000, "longestRunning": 45, "totalRunning": 120, "performanceScore": 0.87 }, { "text": "Just Do It. Summer sale starts now.", "adCount": 3, "totalReach": 1800000, "longestRunning": 30, "totalRunning": 60, "performanceScore": 0.72 } ], "total": 234, "maxPerformanceScore": 1.0, "nextCursor": 5, "hasMore": true } } } } ``` --- ### brandSpy.getHeadlines Get analysis of a company's ad headlines. Same input schema and response structure as `brandSpy.getAdCopies` but analyzes headline/title text instead of body text. **Type:** query | **Auth:** required **Input:** Same as `brandSpy.getAdCopies` **Example request:** ``` GET /brandSpy.getHeadlines?input={"json":{"companyName":"Nike","sortBy":"performanceScore","limit":5}} ``` **Example response:** ```json { "result": { "data": { "json": { "copies": [ { "text": "Just Do It", "adCount": 12, "totalReach": 5000000, "longestRunning": 90, "totalRunning": 300, "performanceScore": 0.95 } ], "total": 150, "maxPerformanceScore": 1.0, "nextCursor": 5, "hasMore": true } } } } ``` --- ### brandSpy.getLandingPages Get a company's landing page distribution — which URLs they drive traffic to. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | companyName | string | yes | — | Advertiser name | | cursor | number | no | — | Pagination cursor | | limit | number | no | 10 | Results per page | | dateFrom | string | no | — | ISO date filter start | | dateTo | string | no | — | ISO date filter end | | status | string | no | "all" | "active", "inactive", or "all" | | mediaType | string | no | "all" | "image", "video", or "all" | | language | string | no | — | Language code filter | | sortBy | string | no | "adCount" | "adCount" or "distribution" | **Example request:** ``` GET /brandSpy.getLandingPages?input={"json":{"companyName":"Nike","sortBy":"distribution"}} ``` **Example response:** ```json { "result": { "data": { "json": { "landingPages": [ { "url": "https://nike.com/running", "adCount": 45, "distribution": 0.32 }, { "url": "https://nike.com/sale", "adCount": 28, "distribution": 0.20 }, { "url": "https://nike.com/new-arrivals", "adCount": 15, "distribution": 0.11 } ], "total": 12, "totalAds": 140, "nextCursor": 3, "hasMore": true } } } } ``` --- ### brandSpy.getTimeline Get a visual timeline of a company's ad launches and pauses. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | companyName | string | yes | — | Advertiser name | | cursor | number | no | — | Pagination cursor | | limit | number | no | 20 | Results per page | | timeRange | string | no | "1month" | "1week", "1month", "3months", "6months", "1year" | | dateFrom | string | no | — | ISO date filter start | | dateTo | string | no | — | ISO date filter end | | status | string | no | "all" | "active", "inactive", or "all" | | mediaType | string | no | "all" | "image", "video", or "all" | | language | string | no | — | Language code filter | **Example request:** ``` GET /brandSpy.getTimeline?input={"json":{"companyName":"Nike","timeRange":"3months"}} ``` **Example response:** ```json { "result": { "data": { "json": { "ads": [ { "id": 12345, "platform": "facebook", "thumbnail": "https://media.adscan.ai/thumbs/12345.jpg", "mediaType": "image", "startDate": 1717200000000, "endDate": null, "isActive": true }, { "id": 12300, "platform": "instagram", "thumbnail": "https://media.adscan.ai/thumbs/12300.jpg", "mediaType": "video", "startDate": 1714521600000, "endDate": 1716000000000, "isActive": false } ], "dateRange": { "start": 1714521600000, "end": 1717200000000 }, "nextCursor": 12299, "hasMore": true } } } } ``` --- ### brandSpy.listTopAdvertisers List the top advertisers in the database ranked by ad count and reach. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Default | |-------|------|----------|---------| | limit | number | no | 200 | **Example request:** ``` GET /brandSpy.listTopAdvertisers?input={"json":{"limit":3}} ``` **Example response:** ```json { "result": { "data": { "json": [ { "advertiserId": 100, "company": "Nike", "adCount": 2340, "totalViews": 50000000, "totalSpend": 0, "brandLogo": "https://media.adscan.ai/logos/nike.jpg", "pageId": "123456", "platforms": ["facebook", "instagram"] }, { "advertiserId": 200, "company": "Adidas", "adCount": 1890, "totalViews": 42000000, "totalSpend": 0, "brandLogo": "https://media.adscan.ai/logos/adidas.jpg", "pageId": "789012", "platforms": ["facebook", "instagram", "youtube"] } ] } } } ``` --- ### brandSpy.listSimilarAdvertisers Find brands similar to a given brand — the "More brands like X" row on the Brand Spy overview. Similarity is primarily semantic: the nearest advertisers to the brand's ad-embedding centroid (cosine similarity). Brands with no embedded ads fall back to the count of shared Facebook page categories ranked by popularity (total views). The brand is resolved by name the same way the rest of Brand Spy resolves it. Returns an empty array when the brand can't be identified or has no similar advertisers. **Type:** query | **Auth:** required **Input:** (provide `companyName` OR `advertiserId`; if both are given, `advertiserId` wins) | Field | Type | Required | Default | |-------|------|----------|---------| | companyName | string | no\* | — | | advertiserId | number | no\* | — | | limit | number | no | 12 (max 50) | | includeTags | boolean | no | false | \*One of `companyName` / `advertiserId` is required. Look up the exact `companyName` with `ads.listTopCompanies` first. **Example request:** ``` GET /brandSpy.listSimilarAdvertisers?input={"json":{"companyName":"Nike","limit":5}} ``` **Example response:** an array of advertiser rows with the same shape as `brandSpy.listTopAdvertisers` (`advertiserId`, `company`, `adCount`, `totalViews`, `brandLogo`, `pageId`, `platforms`, …). **Public REST equivalent:** `GET /api/brand/similar?company=Nike&limit=5` (Foreplay-shaped brand list). --- ### companies.follow Follow a company to track their ads. Used with `companyNames: "FOLLOWED"` filter in ads.list. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | advertiserId | number | yes | **Example request:** ``` POST /companies.follow Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"advertiserId":100}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true, "advertiserId": 100 } } } } ``` --- ### companies.unfollow Unfollow a company. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | advertiserId | number | yes | **Example request:** ``` POST /companies.unfollow Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"advertiserId":100}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### companies.listFollowed List all companies the current user follows. **Type:** query | **Auth:** required **Input:** none **Example request:** ``` GET /companies.listFollowed ``` **Example response:** ```json { "result": { "data": { "json": [ { "advertiserId": 100, "name": "Nike", "profilePicUrl": "https://media.adscan.ai/logos/nike.jpg", "adCount": 2340 }, { "advertiserId": 200, "name": "Adidas", "profilePicUrl": "https://media.adscan.ai/logos/adidas.jpg", "adCount": 1890 } ] } } } ``` --- ### companies.isFollowing Check if the current user is following a specific company. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | advertiserId | number | yes | **Example request:** ``` GET /companies.isFollowing?input={"json":{"advertiserId":100}} ``` **Example response:** ```json { "result": { "data": { "json": { "isFollowing": true } } } } ``` --- ### auth.me Get current user info. Returns null if not authenticated (tolerant — doesn't fail without auth). **Type:** query | **Auth:** tolerant **Input:** none **Example request:** ``` GET /auth.me ``` **Example response (authenticated):** ```json { "result": { "data": { "json": { "name": "John Doe", "email": "john@example.com", "image": "https://lh3.googleusercontent.com/a/photo.jpg" } } } } ``` **Example response (not authenticated):** ```json { "result": { "data": { "json": null } } } ``` --- ### auth.updateName Update the current user's display name. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | name | string | yes | 1-100 characters | **Example request:** ``` POST /auth.updateName Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"name":"John Smith"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true, "name": "John Smith" } } } } ``` --- ### auth.updateInstagramUsername Update the current user's linked Instagram username. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | instagramUsername | string or null | yes | 1-30 chars, alphanumeric + dots + underscores. Set null to remove. | **Example request:** ``` POST /auth.updateInstagramUsername Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"instagramUsername":"john_doe"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true, "instagramUsername": "john_doe" } } } } ``` --- ### apiKeys.create Create a new API key. The plaintext key is ONLY returned at creation time — store it securely. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | name | string | yes | — | Human-readable name for the key | | isAdmin | boolean | no | false | Whether the key has admin permissions | **Example request:** ``` POST /apiKeys.create Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"name":"My Integration"}} ``` **Example response:** ```json { "result": { "data": { "json": { "id": "clx123abc", "key": "adscan_live_704188141c4ae880fcc8d30d0bd033c5a7f1878a6c0c6216634fd5b353d2bf3f", "name": "My Integration", "isAdmin": false, "createdAt": "2025-06-15T10:30:00.000Z" } } } } ``` --- ### apiKeys.list List all API keys for the current user. Does NOT return the plaintext key. **Type:** query | **Auth:** required **Input:** none **Example request:** ``` GET /apiKeys.list ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": "clx123abc", "name": "My Integration", "isAdmin": false, "lastUsedAt": "2025-06-20T14:00:00.000Z", "createdAt": "2025-06-15T10:30:00.000Z" } ] } } } ``` --- ### apiKeys.revoke Revoke (permanently disable) an API key. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | id | string | yes | **Example request:** ``` POST /apiKeys.revoke Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":"clx123abc"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### teams.create Create a new team. The creator becomes the owner. Optionally migrates existing personal data. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | name | string | yes | Team name | | description | string | no | Team description | | migrateExistingData | boolean | no | Migrate personal boards and ads to the team | **Example request:** ``` POST /teams.create Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"name":"Marketing Team","migrateExistingData":true}} ``` **Example response:** ```json { "result": { "data": { "json": { "id": 3, "name": "Marketing Team", "slug": "marketing-team", "inviteCode": "abc123xyz", "migratedBoards": 5, "migratedAds": 120 } } } } ``` --- ### teams.get Get full team details including members and pending invites. **Type:** query | **Auth:** required (must be team member) **Input:** | Field | Type | Required | |-------|------|----------| | id | number | yes | **Example request:** ``` GET /teams.get?input={"json":{"id":3}} ``` **Example response:** ```json { "result": { "data": { "json": { "id": 3, "name": "Marketing Team", "slug": "marketing-team", "description": "Our marketing ad research team", "inviteCode": "abc123xyz", "createdAt": "2025-06-01T00:00:00.000Z", "owner": { "id": "user_abc", "name": "John Doe", "email": "john@example.com" }, "memberCount": 5, "myRole": "admin", "isOwner": true } } } } ``` --- ### teams.list List all teams the current user belongs to. **Type:** query | **Auth:** required **Input:** none **Example request:** ``` GET /teams.list ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": 3, "name": "Marketing Team", "slug": "marketing-team", "description": "Our marketing ad research team", "inviteCode": "abc123xyz", "createdAt": "2025-06-01T00:00:00.000Z", "owner": { "id": "user_abc", "name": "John Doe" }, "memberCount": 5, "myRole": "admin", "isOwner": true } ] } } } ``` --- ### teams.update Update team name and/or description. Requires admin or owner role. **Type:** mutation | **Auth:** required (admin or owner) **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | | name | string | no | | description | string | no | **Example request:** ``` POST /teams.update Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"teamId":3,"name":"Growth Marketing Team"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### teams.delete Delete a team. Only the team owner can delete. **Type:** mutation | **Auth:** required (owner only) **Input:** | Field | Type | Required | |-------|------|----------| | id | number | yes | **Example request:** ``` POST /teams.delete Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":3}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### teams.leave Leave a team. The owner cannot leave their own team (must transfer or delete). **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | **Example request:** ``` POST /teams.leave Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"teamId":3}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### teams.listMembers List all members of a team with their roles. **Type:** query | **Auth:** required (must be team member) **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | **Example request:** ``` GET /teams.listMembers?input={"json":{"teamId":3}} ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": 1, "userId": "user_abc", "role": "admin", "joinedAt": "2025-06-01T00:00:00.000Z", "user": { "name": "John Doe", "email": "john@example.com", "image": "https://lh3.googleusercontent.com/a/photo.jpg" } }, { "id": 2, "userId": "user_def", "role": "member", "joinedAt": "2025-06-10T00:00:00.000Z", "user": { "name": "Jane Smith", "email": "jane@example.com", "image": null } } ] } } } ``` --- ### teams.inviteByEmail Invite a user to a team by email. Sends an invitation email with a join link. **Type:** mutation | **Auth:** required (admin or owner) **Input:** | Field | Type | Required | Default | |-------|------|----------|---------| | teamId | number | yes | — | | email | string | yes | — | | role | string | no | "member" | **Example request:** ``` POST /teams.inviteByEmail Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"teamId":3,"email":"jane@example.com","role":"member"}} ``` **Example response:** ```json { "result": { "data": { "json": { "id": 5, "email": "jane@example.com", "token": "invite_token_xyz", "inviteUrl": "https://adscan.ai/teams/invite/invite_token_xyz", "expiresAt": "2025-07-15T00:00:00.000Z", "teamName": "Marketing Team" } } } } ``` --- ### teams.acceptInvite Accept a team invitation using the invite token from the email link. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | token | string | yes | **Example request:** ``` POST /teams.acceptInvite Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"token":"invite_token_xyz"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true, "teamId": 3 } } } } ``` --- ### teams.removeMember Remove a member from a team. **Type:** mutation | **Auth:** required (admin or owner) **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | | userId | string | yes | **Example request:** ``` POST /teams.removeMember Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"teamId":3,"userId":"user_def"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### teams.updateRole Update a team member's role (admin or member). **Type:** mutation | **Auth:** required (admin or owner) **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | teamId | number | yes | — | | userId | string | yes | — | | role | string | yes | "admin" or "member" | **Example request:** ``` POST /teams.updateRole Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"teamId":3,"userId":"user_def","role":"admin"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### teams.getActivity Get the team's activity log with pagination. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Default | |-------|------|----------|---------| | teamId | number | yes | — | | limit | number | no | 20 | | offset | number | no | 0 | **Example request:** ``` GET /teams.getActivity?input={"json":{"teamId":3,"limit":5}} ``` **Example response:** ```json { "result": { "data": { "json": { "activities": [ { "id": 100, "action": "saved_ad", "targetType": "ad", "targetId": "12345", "metadata": { "company": "Nike", "boardName": "Inspiration" }, "createdAt": "2025-06-20T14:00:00.000Z", "user": { "id": "user_abc", "name": "John Doe", "email": "john@example.com", "image": "https://lh3.googleusercontent.com/a/photo.jpg" } } ], "nextCursor": 99 } } } } ``` --- ### teams.getStats Get team statistics: member count, board count, saved ads, activity count. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | **Example request:** ``` GET /teams.getStats?input={"json":{"teamId":3}} ``` **Example response:** ```json { "result": { "data": { "json": { "memberCount": 5, "boardCount": 12, "totalSavedAds": 450, "activityCount": 1200 } } } } ``` --- ### teams.regenerateInviteCode Regenerate the team's invite link code. Invalidates the previous code. **Type:** mutation | **Auth:** required (owner only) **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | **Example request:** ``` POST /teams.regenerateInviteCode Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"teamId":3}} ``` **Example response:** ```json { "result": { "data": { "json": { "inviteCode": "new_code_xyz789" } } } } ``` --- ### teams.listPendingInvites List pending (not yet accepted) team invitations. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | **Example request:** ``` GET /teams.listPendingInvites?input={"json":{"teamId":3}} ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": 5, "email": "jane@example.com", "status": "pending", "expiresAt": "2025-07-15T00:00:00.000Z", "invitedBy": "user_abc", "invitedByUser": { "name": "John Doe", "email": "john@example.com" } } ] } } } ``` --- ### teams.cancelInvite Cancel a pending team invitation. **Type:** mutation | **Auth:** required (admin or owner) **Input:** | Field | Type | Required | |-------|------|----------| | inviteId | number | yes | **Example request:** ``` POST /teams.cancelInvite Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"inviteId":5}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### teams.validateInviteCode Validate a team invite code and get basic team info. No auth required. **Type:** query | **Auth:** none **Input:** | Field | Type | Required | |-------|------|----------| | code | string | yes | **Example request:** ``` GET /teams.validateInviteCode?input={"json":{"code":"abc123xyz"}} ``` **Example response:** ```json { "result": { "data": { "json": { "valid": true, "teamId": 3, "teamName": "Marketing Team" } } } } ``` --- ### teams.joinTeam Join a team using an invite code (alternative to email invitation). **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | inviteCode | string | yes | **Example request:** ``` POST /teams.joinTeam Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"inviteCode":"abc123xyz"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true, "teamId": 3 } } } } ``` --- ### teams.migrateData Migrate the current user's personal boards and ads to a team. Can be re-run. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | **Example request:** ``` POST /teams.migrateData Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"teamId":3}} ``` **Example response:** ```json { "result": { "data": { "json": { "migratedBoards": 5, "migratedAds": 120 } } } } ``` --- ### publicAds.list Public ad search — no authentication required. Returns ads in a simplified legacy format. **Type:** query | **Auth:** none **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | cursor | number | no | — | Pagination cursor | | limit | number | no | 20 | Results per page | | searchQuery | string | no | — | Full-text search | | companyNames | string[] | no | — | Filter by company names | | ctaTypes | string[] | no | — | Filter by CTA text | | platforms | string[] | no | — | Filter by platform | | formats | string[] | no | — | Filter by format | | viewsMin | number | no | — | Min views | | viewsMax | number | no | — | Max views | | dateFrom | string | no | — | ISO date start | | dateTo | string | no | — | ISO date end | | sortBy | string | no | "date" | "date" or "views" | **Example request:** ``` GET /publicAds.list?input={"json":{"limit":2,"searchQuery":"nike","sortBy":"views"}} ``` **Example response:** ```json { "result": { "data": { "json": { "ads": [ { "id": "12345", "company": "Nike", "brandLogo": "https://media.adscan.ai/logos/nike.jpg", "date": "2025-06-15T10:30:00.000Z", "status": "active", "title": "Just Do It", "cardBody": "Step into greatness with our new collection.", "cardLinkDescription": "Nike.com", "cardLinkUrl": "https://nike.com/new", "poster": "https://media.adscan.ai/ads/12345_0.jpg", "videoUrl": "", "ctaText": "Shop Now", "videoLength": null, "displayFormat": "image", "pageUrl": "https://facebook.com/nike", "advertisedUrl": "https://nike.com", "hash": "abc123def456", "youtubeViews": 0, "reach": 500000, "spend": null, "headline": "Just Do It", "sourcePlatform": "facebook" } ], "nextCursor": 12344, "hasMore": true } } } } ``` --- ### publicAds.listLinkedIn Public LinkedIn ad search — no authentication required. **Type:** query | **Auth:** none **Input:** | Field | Type | Required | Default | |-------|------|----------|---------| | cursor | number | no | — | | limit | number | no | 20 | | searchQuery | string | no | — | | companyNames | string[] | no | — | | ctaTypes | string[] | no | — | | formats | string[] | no | — | | dateFrom | string | no | — | | dateTo | string | no | — | | viewsMin | number | no | — | | viewsMax | number | no | — | | sortBy | string | no | "date" | **Example request:** ``` GET /publicAds.listLinkedIn?input={"json":{"limit":2,"searchQuery":"hiring"}} ``` **Example response:** ```json { "result": { "data": { "json": { "ads": [ { "id": "67890", "company": "Google", "brandLogo": "https://media.adscan.ai/logos/google.jpg", "date": "2025-06-10T00:00:00.000Z", "status": "active", "title": "We're Hiring Engineers", "cardBody": "Join our team and build the future of search.", "poster": "https://media.adscan.ai/ads/67890_0.jpg", "videoUrl": "", "ctaText": "Apply Now", "displayFormat": "image", "reach": 200000, "headline": "We're Hiring Engineers", "sourcePlatform": "linkedin" } ], "nextCursor": 67889, "hasMore": true } } } } ``` --- ### publicBoards.get Get a public board by its slug. Increments the board's view counter on each request. **Type:** query | **Auth:** none **Input:** | Field | Type | Required | |-------|------|----------| | slug | string | yes | **Example request:** ``` GET /publicBoards.get?input={"json":{"slug":"best-facebook-ads-2025"}} ``` **Example response:** ```json { "result": { "data": { "json": { "id": 42, "name": "Best Facebook Ads 2025", "slug": "best-facebook-ads-2025", "description": "Curated collection of the best Facebook ads in 2025", "isPublic": 1, "views": 1234, "created_at": "2025-03-15T10:00:00.000Z", "authorId": "user_abc", "parentBoardId": null, "author": { "id": "user_abc", "name": "John Doe", "image": "https://lh3.googleusercontent.com/a/photo.jpg" } } } } } ``` --- ### publicBoards.listAds List ads in a public board with pagination and optional search. **Type:** query | **Auth:** none **Input:** | Field | Type | Required | Default | |-------|------|----------|---------| | slug | string | yes | — | | cursor | number | no | — | | limit | number | no | 20 | | searchQuery | string | no | — | **Example request:** ``` GET /publicBoards.listAds?input={"json":{"slug":"best-facebook-ads-2025","limit":5}} ``` **Example response:** ```json { "result": { "data": { "json": { "ads": [ { "id": 12345, "company": "Nike", "brandLogo": "https://media.adscan.ai/logos/nike.jpg", "date": "2025-06-15T10:30:00.000Z", "status": 1, "title": "Just Do It", "cardBody": "Step into greatness.", "poster": "https://media.adscan.ai/ads/12345_0.jpg", "videoUrl": null, "ctaText": "Shop Now", "displayFormat": "image", "reach": 500000, "headline": "Just Do It" } ], "nextCursor": 12344, "hasMore": true } } } } ``` --- ### publicBoards.listAll List all public boards with their authors and ad counts. **Type:** query | **Auth:** none **Input:** none **Example request:** ``` GET /publicBoards.listAll ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": 42, "name": "Best Facebook Ads 2025", "slug": "best-facebook-ads-2025", "description": "Curated collection of the best Facebook ads", "views": 1234, "createdAt": "2025-03-15T10:00:00.000Z", "author": { "name": "John Doe", "email": "john@example.com", "image": "https://lh3.googleusercontent.com/a/photo.jpg" }, "adCount": 87 } ] } } } ``` --- ### admachine.me Get current user session with their AdMachine teams. **Type:** query | **Auth:** required **Input:** none **Example request:** ``` GET /admachine.me ``` **Example response:** ```json { "result": { "data": { "json": { "user": { "id": "user_abc", "email": "john@example.com", "name": "John Doe", "image": "https://lh3.googleusercontent.com/a/photo.jpg" }, "teams": [ { "id": 1, "name": "My Agency", "slug": "my-agency", "role": "admin" } ] } } } } ``` --- ### admachine.analyzeDomain Analyze a business domain using AI (Claude Sonnet 4) to extract brand information, industry, tone, and suggested competitors. **Type:** query | **Auth:** none **Input:** | Field | Type | Required | |-------|------|----------| | domain | string | yes | **Example request:** ``` GET /admachine.analyzeDomain?input={"json":{"domain":"nike.com"}} ``` **Example response:** ```json { "result": { "data": { "json": { "businessName": "Nike", "industry": "Athletic Apparel & Footwear", "description": "Global leader in athletic footwear, apparel, and sports equipment.", "tone": "Inspirational, bold, empowering", "targetAudience": "Athletes, fitness enthusiasts, and active lifestyle consumers aged 16-45", "usp": "Premium performance athletic wear with iconic branding and athlete endorsements", "suggestedCompetitors": ["Adidas", "Puma", "Under Armour", "New Balance", "Reebok"] } } } } ``` --- ### admachine.matchCompetitors Match competitor names against the Adscan database to find existing advertisers. Uses fuzzy matching. **Type:** query | **Auth:** none **Input:** | Field | Type | Required | |-------|------|----------| | names | string[] | yes | **Example request:** ``` GET /admachine.matchCompetitors?input={"json":{"names":["Adidas","Puma","Under Armour","SomeUnknownBrand"]}} ``` **Example response:** ```json { "result": { "data": { "json": { "matched": [ { "name": "Adidas", "logoUrl": "https://media.adscan.ai/logos/adidas.jpg", "adCount": 1890 }, { "name": "PUMA", "logoUrl": "https://media.adscan.ai/logos/puma.jpg", "adCount": 920 }, { "name": "Under Armour", "logoUrl": "https://media.adscan.ai/logos/ua.jpg", "adCount": 650 } ], "unmatched": ["SomeUnknownBrand"] } } } } ``` --- ### admachine.searchAdvertisers Autocomplete search for advertisers. Returns up to 6 matches. **Type:** query | **Auth:** none **Input:** | Field | Type | Required | |-------|------|----------| | query | string | yes | **Example request:** ``` GET /admachine.searchAdvertisers?input={"json":{"query":"nik"}} ``` **Example response:** ```json { "result": { "data": { "json": { "results": [ { "name": "Nike", "logoUrl": "https://media.adscan.ai/logos/nike.jpg", "adCount": 2340 }, { "name": "Nike Football", "logoUrl": "https://media.adscan.ai/logos/nikefb.jpg", "adCount": 456 }, { "name": "Nike Running", "logoUrl": null, "adCount": 189 } ] } } } } ``` --- ### admachine.loadTopAds Load top-performing ads from specified companies. Uses round-robin to ensure diversity across companies. **Type:** query | **Auth:** none **Input:** | Field | Type | Required | Default | |-------|------|----------|---------| | companyNames | string[] | yes | — | | limit | number | no | 10 | **Example request:** ``` GET /admachine.loadTopAds?input={"json":{"companyNames":["Nike","Adidas"],"limit":4}} ``` **Example response:** ```json { "result": { "data": { "json": { "ads": [ { "id": 12345, "platform": "facebook", "advertiser": "Nike", "advertiserLogo": "https://media.adscan.ai/logos/nike.jpg", "headline": "Just Do It", "body": "Step into greatness with our new collection.", "imageUrl": "https://media.adscan.ai/ads/12345_0.jpg", "mediaType": "image", "views": 500000 }, { "id": 23456, "platform": "instagram", "advertiser": "Adidas", "advertiserLogo": "https://media.adscan.ai/logos/adidas.jpg", "headline": "Impossible Is Nothing", "body": "New Ultraboost collection.", "imageUrl": "https://media.adscan.ai/ads/23456_0.jpg", "mediaType": "image", "views": 320000 } ] } } } } ``` --- ### admachine.generateImage Generate an AI ad image based on brand info and a source ad for inspiration. Uses AI image generation (default model: bytedance-seed/seedream-4.5). Uploads result to R2 storage. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | brandName | string | yes | — | Brand name for the generated ad | | brandColors | string[] | yes | — | Brand color hex codes | | brandLogoUrl | string | no | — | Brand logo URL | | industry | string | no | — | Industry context | | style | string | no | — | Style direction | | model | string | no | "bytedance-seed/seedream-4.5" | AI model to use | | sourceAdImageUrl | string | no | — | Source ad image for inspiration | | sourceAdAdvertiser | string | no | — | Source ad's advertiser | | sourceAdHeadline | string | no | — | Source ad's headline | | sourceAdBody | string | no | — | Source ad's body text | **Example request:** ``` POST /admachine.generateImage Content-Type: application/json Authorization: Bearer adscan_live_xxx { "json": { "brandName": "MyBrand", "brandColors": ["#FF5733", "#33FF57"], "industry": "E-Commerce", "sourceAdImageUrl": "https://media.adscan.ai/ads/12345_0.jpg", "sourceAdAdvertiser": "Nike", "sourceAdHeadline": "Just Do It", "sourceAdBody": "Step into greatness." } } ``` **Example response:** ```json { "result": { "data": { "json": { "imageUrl": "https://media.adscan.ai/ai-images/generated_abc123.png", "prompt": "Create a modern e-commerce ad image for MyBrand with colors #FF5733 and #33FF57...", "model": "bytedance-seed/seedream-4.5" } } } } ``` --- ### admachine.generateCopy Generate AI ad copy variations based on brand info and top-performing competitor ads. Uses Grok for generation. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | brandName | string | yes | — | Brand name | | brandColors | string[] | yes | — | Brand colors | | tone | string | no | — | Desired tone of voice | | targetAudience | string | no | — | Target audience description | | usp | string | no | — | Unique selling proposition | | industry | string | no | — | Industry context | | generatedImageUrl | string | no | — | URL of the generated image (for context) | | topAds | object[] | yes | — | Top competitor ads for inspiration | | topAds[].body | string | yes | — | Ad body text | | topAds[].headline | string | no | — | Ad headline | | topAds[].reach | number | no | — | Ad reach/views | | topAds[].advertiser | string | no | — | Advertiser name | | count | number | no | 5 | Number of variations to generate | **Example request:** ``` POST /admachine.generateCopy Content-Type: application/json Authorization: Bearer adscan_live_xxx { "json": { "brandName": "MyBrand", "brandColors": ["#FF5733"], "tone": "Bold and inspiring", "targetAudience": "Fitness enthusiasts 25-40", "usp": "Eco-friendly workout gear", "industry": "Athletic Apparel", "topAds": [ { "body": "Just Do It. New collection now.", "headline": "Just Do It", "reach": 500000, "advertiser": "Nike" }, { "body": "Impossible Is Nothing.", "headline": "Impossible Is Nothing", "reach": 320000, "advertiser": "Adidas" } ], "count": 3 } } ``` **Example response:** ```json { "result": { "data": { "json": { "concepts": [ { "headline": "Sweat Green, Train Mean", "body": "Our eco-friendly workout gear is built for athletes who care about performance AND the planet. Made from 100% recycled materials.", "cta": "Shop Now", "angle": "Eco-performance fusion", "rationale": "Combines the sustainability USP with high-performance messaging inspired by Nike's bold, action-oriented approach." }, { "headline": "Your Workout. Your Planet.", "body": "Every rep counts. So does every choice. MyBrand workout gear — designed for peak performance with zero environmental compromise.", "cta": "Discover More", "angle": "Conscious athlete", "rationale": "Targets the growing eco-conscious fitness demographic with empowering language similar to Adidas' motivational style." }, { "headline": "Built Different. Built Better.", "body": "Premium eco-friendly materials. Zero-waste manufacturing. Maximum performance. This is workout gear evolved.", "cta": "Get Yours", "angle": "Premium quality + sustainability", "rationale": "Emphasizes premium positioning and innovation, differentiating from competitors through sustainability as a quality marker." } ] } } } } ``` --- ### admachine.createTeam Create an AdMachine team workspace. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | name | string | yes | **Example request:** ``` POST /admachine.createTeam Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"name":"My Agency"}} ``` **Example response:** ```json { "result": { "data": { "json": { "id": 1, "name": "My Agency", "slug": "my-agency" } } } } ``` --- ### admachine.getMyTeams List the current user's AdMachine teams. **Type:** query | **Auth:** required **Input:** none **Example request:** ``` GET /admachine.getMyTeams ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": 1, "name": "My Agency", "slug": "my-agency", "role": "admin", "memberCount": 3, "isOwner": true } ] } } } ``` --- ### admachine.updateTeam Update an AdMachine team's name. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | | name | string | yes | **Example request:** ``` POST /admachine.updateTeam Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"teamId":1,"name":"My Agency Pro"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### admachine.inviteMember Invite a member to an AdMachine team. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Default | |-------|------|----------|---------| | teamId | number | yes | — | | email | string | yes | — | | role | string | no | "member" | **Example request:** ``` POST /admachine.inviteMember Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"teamId":1,"email":"designer@example.com","role":"member"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### admachine.joinTeam Join an AdMachine team via invite token. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | token | string | yes | **Example response:** ```json { "result": { "data": { "json": { "teamId": 1 } } } } ``` --- ### admachine.removeMember Remove a member from an AdMachine team. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | | userId | string | yes | **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### admachine.createProject Create a new AdMachine project for AI ad creation. A project stores brand settings and manages a kanban board of ad concepts. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | teamId | number | yes | — | Team this project belongs to | | name | string | yes | — | Project name | | domain | string | no | — | Business website domain | | industry | string | no | — | Business industry | | description | string | no | — | Business description | | brandColors | string[] | no | — | Brand color hex codes | | tone | string | no | — | Brand tone of voice | | targetAudience | string | no | — | Target audience description | | usp | string | no | — | Unique selling proposition | | brandLogoUrl | string | no | — | Brand logo URL | | imageModel | string | no | — | Preferred AI image model | | competitors | object[] | no | — | Competitor brands | | competitors[].name | string | yes | — | Competitor name | | competitors[].logoUrl | string or null | yes | — | Competitor logo | | competitors[].adCount | number | yes | — | Number of ads in database | **Example request:** ``` POST /admachine.createProject Content-Type: application/json Authorization: Bearer adscan_live_xxx { "json": { "teamId": 1, "name": "Summer Campaign 2025", "domain": "mybrand.com", "industry": "Athletic Apparel", "description": "Eco-friendly workout gear brand", "brandColors": ["#FF5733", "#33FF57"], "tone": "Bold and inspiring", "targetAudience": "Fitness enthusiasts 25-40", "usp": "100% recycled materials", "competitors": [ { "name": "Nike", "logoUrl": "https://media.adscan.ai/logos/nike.jpg", "adCount": 2340 }, { "name": "Adidas", "logoUrl": "https://media.adscan.ai/logos/adidas.jpg", "adCount": 1890 } ] } } ``` **Example response:** ```json { "result": { "data": { "json": { "id": "proj_abc123" } } } } ``` --- ### admachine.getProject Get full project details including competitors and brand settings. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | id | string | yes | **Example request:** ``` GET /admachine.getProject?input={"json":{"id":"proj_abc123"}} ``` **Example response:** ```json { "result": { "data": { "json": { "id": "proj_abc123", "name": "Summer Campaign 2025", "domain": "mybrand.com", "industry": "Athletic Apparel", "description": "Eco-friendly workout gear brand", "brandColors": ["#FF5733", "#33FF57"], "tone": "Bold and inspiring", "targetAudience": "Fitness enthusiasts 25-40", "usp": "100% recycled materials", "brandLogoUrl": null, "imageModel": "bytedance-seed/seedream-4.5", "teamId": 1, "createdBy": "user_abc", "createdAt": "2025-06-01T00:00:00.000Z", "updatedAt": "2025-06-15T00:00:00.000Z", "competitors": [ { "id": "comp_1", "name": "Nike", "logoUrl": "https://media.adscan.ai/logos/nike.jpg", "adCount": 2340 }, { "id": "comp_2", "name": "Adidas", "logoUrl": "https://media.adscan.ai/logos/adidas.jpg", "adCount": 1890 } ] } } } } ``` --- ### admachine.listProjects List all projects in a team with summary info. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | teamId | number | yes | **Example request:** ``` GET /admachine.listProjects?input={"json":{"teamId":1}} ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": "proj_abc123", "name": "Summer Campaign 2025", "domain": "mybrand.com", "industry": "Athletic Apparel", "cardCount": 15, "competitorCount": 2, "updatedAt": "2025-06-15T00:00:00.000Z" } ] } } } ``` --- ### admachine.updateProject Update project settings (brand info, model, etc.). **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | id | string | yes | | name | string | no | | domain | string | no | | industry | string | no | | description | string | no | | brandColors | string[] | no | | brandLogoUrl | string | no | | tone | string | no | | targetAudience | string | no | | usp | string | no | | imageModel | string | no | **Example request:** ``` POST /admachine.updateProject Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":"proj_abc123","tone":"Playful and energetic","imageModel":"flux-1.1-pro"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### admachine.deleteProject Delete an AdMachine project and all its cards. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | id | string | yes | **Example request:** ``` POST /admachine.deleteProject Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":"proj_abc123"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### admachine.addCompetitor Add a competitor brand to a project. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Default | |-------|------|----------|---------| | projectId | string | yes | — | | name | string | yes | — | | logoUrl | string or null | yes | — | | adCount | number | no | 0 | **Example request:** ``` POST /admachine.addCompetitor Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"projectId":"proj_abc123","name":"Puma","logoUrl":"https://media.adscan.ai/logos/puma.jpg","adCount":920}} ``` **Example response:** ```json { "result": { "data": { "json": { "id": "comp_3" } } } } ``` --- ### admachine.removeCompetitor Remove a competitor from a project. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | id | string | yes | **Example request:** ``` POST /admachine.removeCompetitor Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":"comp_3"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### admachine.addCards Add ad cards to a project's kanban board. Each card references a source ad for inspiration. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | projectId | string | yes | — | Project to add cards to | | cards | object[] | yes | — | Cards to add | | cards[].sourceAd | object | yes | — | Source ad data | | cards[].sourceAd.id | number | no | — | Internal ad ID | | cards[].sourceAd.advertiser | string | yes | — | Advertiser name | | cards[].sourceAd.advertiserLogo | string or null | yes | — | Logo URL | | cards[].sourceAd.body | string | yes | — | Ad body text | | cards[].sourceAd.headline | string or null | yes | — | Ad headline | | cards[].sourceAd.imageUrl | string or null | yes | — | Ad image URL | | cards[].sourceAd.mediaType | string or null | yes | — | "image" or "video" | | cards[].sourceAd.views | number | yes | — | View count | | cards[].sourceAd.platform | string | yes | — | Platform name | | cards[].column | string | no | "review" | Initial column | **Example request:** ``` POST /admachine.addCards Content-Type: application/json Authorization: Bearer adscan_live_xxx { "json": { "projectId": "proj_abc123", "cards": [ { "sourceAd": { "id": 12345, "advertiser": "Nike", "advertiserLogo": "https://media.adscan.ai/logos/nike.jpg", "body": "Just Do It. New collection now.", "headline": "Just Do It", "imageUrl": "https://media.adscan.ai/ads/12345_0.jpg", "mediaType": "image", "views": 500000, "platform": "facebook" }, "column": "review" } ] } } ``` **Example response:** ```json { "result": { "data": { "json": { "ids": ["card_xyz789"] } } } } ``` --- ### admachine.moveCard Move a card between kanban columns. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | id | string | yes | Card ID | | column | string | yes | "review", "generating", "to_launch", or "rejected" | **Example request:** ``` POST /admachine.moveCard Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":"card_xyz789","column":"to_launch"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### admachine.updateCard Update a card's generated content (image, copy, status). **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | id | string | yes | Card ID | | column | string | no | Move to column | | generatedImageUrl | string | no | AI-generated image URL | | generatedHeadline | string | no | Generated headline | | generatedBody | string | no | Generated body copy | | generatedCta | string | no | Generated CTA text | | generatedAngle | string | no | Creative angle description | | generatedRationale | string | no | Why this concept works | | generationStatus | string | no | "pending", "generating", "complete", "error" | | generationError | string | no | Error message if failed | | generationPrompt | string | no | Prompt used for generation | | imagePrompt | string | no | Image generation prompt | | imageModelUsed | string | no | Model used for image | | copyDurationMs | number | no | Time to generate copy | | imageDurationMs | number | no | Time to generate image | **Example request:** ``` POST /admachine.updateCard Content-Type: application/json Authorization: Bearer adscan_live_xxx { "json": { "id": "card_xyz789", "generatedImageUrl": "https://media.adscan.ai/ai-images/gen_abc.png", "generatedHeadline": "Sweat Green, Train Mean", "generatedBody": "Eco-friendly workout gear built for peak performance.", "generatedCta": "Shop Now", "generatedAngle": "Eco-performance fusion", "generatedRationale": "Combines sustainability USP with high-performance messaging.", "generationStatus": "complete", "column": "to_launch" } } ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### admachine.removeCard Remove a card from a project. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | id | string | yes | **Example request:** ``` POST /admachine.removeCard Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":"card_xyz789"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### admachine.getCards Get all cards in a project, optionally filtered by column. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Description | |-------|------|----------|-------------| | projectId | string | yes | Project ID | | column | string | no | Filter by column name | **Example request:** ``` GET /admachine.getCards?input={"json":{"projectId":"proj_abc123"}} ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": "card_xyz789", "column": "to_launch", "createdAt": "2025-06-15T10:00:00.000Z", "sourceAd": { "id": "12345", "advertiser": "Nike", "advertiserLogo": "https://media.adscan.ai/logos/nike.jpg", "body": "Just Do It. New collection now.", "headline": "Just Do It", "imageUrl": "https://media.adscan.ai/ads/12345_0.jpg", "mediaType": "image", "views": 500000, "platform": "facebook" }, "generatedImageUrl": "https://media.adscan.ai/ai-images/gen_abc.png", "generatedHeadline": "Sweat Green, Train Mean", "generatedBody": "Eco-friendly workout gear built for peak performance.", "generatedCta": "Shop Now", "generatedAngle": "Eco-performance fusion", "generatedRationale": "Combines sustainability USP with high-performance messaging.", "generationStatus": "complete", "imageModelUsed": "bytedance-seed/seedream-4.5", "copyDurationMs": 2300, "imageDurationMs": 8500 } ] } } } ``` --- ### admachine.clearColumn Clear (delete) all cards in a project column. **Type:** mutation | **Auth:** required **Input:** | Field | Type | Required | |-------|------|----------| | projectId | string | yes | | column | string | yes | **Example request:** ``` POST /admachine.clearColumn Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"projectId":"proj_abc123","column":"rejected"}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### admachine.getActivityLog Get project/team activity log with pagination. **Type:** query | **Auth:** required **Input:** | Field | Type | Required | Default | |-------|------|----------|---------| | teamId | number | yes | — | | projectId | string | no | — | | limit | number | no | 50 | | cursor | number | no | — | **Example request:** ``` GET /admachine.getActivityLog?input={"json":{"teamId":1,"limit":5}} ``` **Example response:** ```json { "result": { "data": { "json": { "items": [ { "id": 50, "action": "card_moved_to_launch", "targetType": "card", "targetId": "card_xyz789", "metadata": { "column": "to_launch", "projectName": "Summer Campaign 2025" }, "createdAt": "2025-06-20T14:00:00.000Z", "user": { "id": "user_abc", "name": "John Doe", "email": "john@example.com", "image": "https://lh3.googleusercontent.com/a/photo.jpg" } } ], "nextCursor": 49 } } } } ``` --- ### aiImages.list List the current user's AI-generated images (most recent 100). **Type:** query | **Auth:** required **Input:** none **Example request:** ``` GET /aiImages.list ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": 1, "url": "https://media.adscan.ai/ai-images/gen_abc123.png", "created_at": "2025-06-15T10:30:00.000Z", "userId": "user_abc" } ] } } } ``` --- ### aiImages.delete Delete an AI-generated image. Only the image owner can delete. **Type:** mutation | **Auth:** required (owner only) **Input:** | Field | Type | Required | |-------|------|----------| | id | number | yes | **Example request:** ``` POST /aiImages.delete Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":1}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ### brandImages.list List the current user's uploaded brand images (most recent 100). **Type:** query | **Auth:** required **Input:** none **Example request:** ``` GET /brandImages.list ``` **Example response:** ```json { "result": { "data": { "json": [ { "id": 1, "url": "https://media.adscan.ai/brand-images/logo_mybrand.png", "created_at": "2025-06-01T00:00:00.000Z", "userId": "user_abc" } ] } } } ``` --- ### brandImages.delete Delete a brand image. Only the image owner can delete. **Type:** mutation | **Auth:** required (owner only) **Input:** | Field | Type | Required | |-------|------|----------| | id | number | yes | **Example request:** ``` POST /brandImages.delete Content-Type: application/json Authorization: Bearer adscan_live_xxx {"json":{"id":1}} ``` **Example response:** ```json { "result": { "data": { "json": { "success": true } } } } ``` --- ## Error Handling All errors follow this format: ```json { "error": { "message": "Error description", "code": -32600, "data": { "code": "BAD_REQUEST", "httpStatus": 400, "path": "ads.list" } } } ``` **Common error codes:** | Code | HTTP Status | Description | |------|-------------|-------------| | `UNAUTHORIZED` | 401 | Missing or invalid API key | | `BAD_REQUEST` | 400 | Invalid input parameters | | `NOT_FOUND` | 404 | Resource not found | | `FORBIDDEN` | 403 | Insufficient permissions (e.g. not team admin) | | `INTERNAL_SERVER_ERROR` | 500 | Server error | --- ## Common Workflows ### 1. Competitive analysis (ad discovery) **Important:** Use `ads.listTopCompanies` first to find the correct company name. ``` 1. GET /ads.listTopCompanies?input={"json":{"name":"nike"}} → Returns exact company name: "nike.com" 2. GET /brandSpy.getOverview?input={"json":{"companyName":"nike.com","status":"active"}} → Stats, demographics, media breakdown 2b. GET /brandSpy.getLandingPages?input={"json":{"companyName":"nike.com"}} → Landing page distribution (URL, ad count, share) 3. GET /brandSpy.getAdCopies?input={"json":{"companyName":"nike.com","sortBy":"performanceScore"}} → Ranked ad copy with performance scores 4. GET /brandSpy.getHeadlines?input={"json":{"companyName":"nike.com","sortBy":"reach"}} → Ranked headlines 5. GET /brandSpy.getLandingPages?input={"json":{"companyName":"nike.com"}} → Landing page distribution 6. GET /brandSpy.getTimeline?input={"json":{"companyName":"nike.com","timeRange":"3months"}} → Ad launch timeline ``` ### 2. Search saved ads and organize into boards ``` 1. GET /ads.list?input={"json":{"searchQuery":"shoes","boardId":"ALL","sortBy":"views","limit":10}} → Searches only YOUR saved ads (not the full database) 2. POST /boards.create → {"json":{"name":"Shoe Ads"}} 3. POST /ads.addToBoard → {"json":{"adId":12345,"boardId":5}} ``` ### 3. AI ad creation (AdMachine) ``` 1. GET /admachine.analyzeDomain?input={"json":{"domain":"mybrand.com"}} 2. GET /admachine.matchCompetitors?input={"json":{"names":["Nike","Adidas"]}} 3. GET /admachine.loadTopAds?input={"json":{"companyNames":["Nike","Adidas"],"limit":10}} 4. POST /admachine.createProject → {"json":{"teamId":1,"name":"Q3 Campaign",...}} 5. POST /admachine.addCards → {"json":{"projectId":"proj_x","cards":[...]}} 6. POST /admachine.generateImage → {"json":{"brandName":"MyBrand","brandColors":["#FF5733"],...}} 7. POST /admachine.generateCopy → {"json":{"brandName":"MyBrand","topAds":[...],...}} 8. POST /admachine.updateCard → {"json":{"id":"card_x","generatedImageUrl":"...","generatedHeadline":"...",...}} 9. POST /admachine.moveCard → {"json":{"id":"card_x","column":"to_launch"}} ``` ### 4. Team collaboration ``` 1. POST /teams.create → {"json":{"name":"Marketing Team"}} 2. POST /teams.inviteByEmail → {"json":{"teamId":3,"email":"colleague@example.com"}} 3. POST /boards.create → {"json":{"name":"Shared Inspiration","teamId":3}} 4. POST /ads.addToBoard → {"json":{"adId":12345,"boardId":10}} 5. GET /teams.getActivity?input={"json":{"teamId":3}} ``` --- ## Rate Limits & Notes - API keys authenticate as the user who created them. - There is no explicit rate limit documented, but be reasonable with request frequency. - Cursor-based pagination: always use the `nextCursor` from the response for the next page. - All dates are ISO 8601 strings (UTC). - Media URLs are served from `media.adscan.ai`. - The `publicAds` and `publicBoards` routers do not require authentication.