API Reference

All endpoints are at https://sponsoric.com/api/ads/.

Authentication

Authenticated endpoints require a Bearer token in the Authorization header:

Authorization: Bearer sk_your_api_key

Your API key (sk_...) is returned when you create a campaign or sign up as a publisher. You can also:

  • Recover it via email: POST /api/auth/api-key with { "email": "you@example.com" }
  • Regenerate it: POST /api/auth/api-key with Authorization: Bearer sk_current_key
  • View it in your dashboard settings
Endpoints marked Auth required will return 401 without a valid key.

Rate limits

All API endpoints are rate-limited to prevent abuse. If you exceed a limit, you'll receive a 429 Too Many Requests response — wait briefly and retry.

Rate limits apply per IP address and are enforced globally across our infrastructure. Limits vary by endpoint based on expected usage patterns. Authenticated requests share the same limits as unauthenticated ones.

For details on how we protect the network from fraud and abuse, see Fraud Prevention.


Bonus tiers

Get the current bonus credit tiers. When an advertiser adds funds above a threshold amount in a single payment, they receive bonus budget credits. Each payment is evaluated independently — bonuses are not cumulative across multiple payments. Optionally pass a promo code to see custom tiers.

GET /api/ads/promo-tiers
GET /api/ads/promo-tiers?code=LAUNCH2026
Response (200):
JSON
{
  "tiers": [
    { "minAmountCents": 5000, "bonusCents": 500 },
    { "minAmountCents": 10000, "bonusCents": 1500 },
    { "minAmountCents": 25000, "bonusCents": 4500 },
    { "minAmountCents": 50000, "bonusCents": 10000 }
  ],
  "promoCode": "LAUNCH2026"
}
promoCode is null if no code was applied (default tiers shown). Invalid or expired codes silently return default tiers.

Rate limited: 5 requests per minute per IP when using ?code=.


Analyze product

Scrape a URL and AI-generate ad copy + targeting tags.

POST /api/ads/analyze
Request:
JSON
{ "url": "https://yourproduct.com" }
Response (200):
JSON
{
  "url": "string",
  "name": "string",
  "tagline": "string",
  "headline": "string (under 60 chars)",
  "body": "string (under 150 chars)",
  "ctaText": "string (2-4 words)",
  "tags": ["string"],
  "logo": "string | null (URL)",
  "brandColor": "string (#hex)",
  "safetyScore": "number (1-10)",
  "flagReason": "string | null",
  "safe": "boolean"
}

Analyze site

Classify a publisher site for ad targeting.

POST /api/ads/analyze-site
Request:
JSON
{ "url": "https://yoursite.dev" }
Response (200):
JSON
{
  "url": "string",
  "siteName": "string",
  "description": "string",
  "tags": ["string"],
  "safetyScore": "number (1-10)",
  "flagReason": "string | null",
  "safe": "boolean"
}

Create campaign (agents)

Create an advertiser account and ad campaign. Two-step flow: get payment details, send USDC, submit proof.

POST /api/ads/campaign
Request:
JSON
{
  "email": "string",
  "name": "string",
  "url": "string",
  "headline": "string",
  "body": "string",
  "ctaText": "string",
  "tags": ["string"],
  "budgetCents": "number (min 500 = $5)",
  "logo": "string (optional, URL)",
  "brandColor": "string (optional, #hex)",
  "tagline": "string (optional)",
  "startsAt": "string (optional, ISO date)",
  "endsAt": "string (optional, ISO date)",
  "promoCode": "string (optional, bonus credit code)"
}
Response (402, no Authorization header):
JSON
{
  "status": 402,
  "payment": {
    "currency": "USDC",
    "currencyAddress": "0x20C000000000000000000000b9537d11c60E8b50",
    "chain": "tempo",
    "chainId": 4217,
    "amount": "string (raw amount with 6 decimals)",
    "amountFormatted": "$X.XX",
    "recipient": "0x...",
    "instructions": "string"
  }
}

Send the exact USDC amount to the recipient on Tempo, then retry with the tx hash:

Authorization: Payment tx=0xYourTransactionHash
Response (200, with valid tx hash):
JSON
{
  "advertiserId": "string",
  "adId": "string",
  "apiKey": "sk_... (save this for authenticated requests)",
  "status": "live",
  "dashboardUrl": "https://sponsoric.com/dashboard",
  "txHash": "string",
  "bonusCents": "number (if a bonus tier was unlocked)",
  "totalBudgetCents": "number (budget + bonus, if applicable)"
}

Create campaign (humans)

Redirect to Stripe Checkout for browser-based payment.

POST /api/ads/checkout

Same request body as /api/ads/campaign. Returns { checkoutUrl } for redirect.


Publisher signup

Create a publisher account. Free, instant.

POST /api/ads/publisher-signup
Request:
JSON
{
  "email": "string",
  "siteName": "string",
  "siteUrl": "string",
  "tags": ["string"],
  "description": "string (optional)",
  "tempoWalletAddress": "string (optional, 0x... — save your private key; you need it to access payouts)"
}
Response (200):
JSON
{
  "ok": true,
  "publisherId": "string",
  "apiKey": "sk_... (save this for authenticated requests)",
  "embedCode": "string (HTML)"
}

Estimate traffic & revenue

Get real estimates for what a campaign or publisher site could expect, based on live network data.

GET /api/ads/estimate?type=advertiser&tags=developer-tools,saas&budgetCents=10000&days=30
GET /api/ads/estimate?type=publisher&tags=developer-tools,saas&monthlyVisitors=10000
Params:
  • typeadvertiser or publisher (required)
  • tags — comma-separated targeting tags (required)
  • budgetCents — campaign budget in cents (advertiser only, default 10000)
  • days — campaign duration (advertiser only, default 30)
  • monthlyVisitors — monthly site visitors (publisher only, default 5000)
Advertiser response:
JSON
{
  "type": "advertiser",
  "network": {
    "activePublishers": 12,
    "activeAds": 8,
    "competitorsForYourTags": 2,
    "networkCtr": "2.50%",
    "avgCostPerClick": "$0.15"
  },
  "estimate": {
    "budget": "$100.00",
    "duration": "30 days",
    "estimatedImpressions": { "daily": 889, "total": 26667 },
    "estimatedClicks": { "daily": 22, "total": 667 },
    "estimatedCostPerClick": "$0.15"
  }
}
Publisher response:
JSON
{
  "type": "publisher",
  "network": {
    "activeAds": 8,
    "adsMatchingYourTags": 3,
    "networkCtr": "2.50%",
    "avgCostPerClick": "$0.06",
    "revenueShare": "70%",
    "networkRPM": "$1.05"
  },
  "estimate": {
    "monthlyVisitors": 10000,
    "estimatedAdFillRate": "45%",
    "estimatedMonthlyImpressions": 4500,
    "estimatedMonthlyClicks": 113,
    "estimatedMonthlyRevenue": "$4.73",
    "estimatedYearlyRevenue": "$56.70",
    "estimatedRPM": "$1.05"
  },
  "projected": {
    "description": "Projected earnings assuming healthy ad inventory matching your tags (60% fill rate)",
    "estimatedMonthlyImpressions": 6000,
    "estimatedMonthlyClicks": 150,
    "estimatedMonthlyRevenue": "$6.30",
    "estimatedYearlyRevenue": "$75.60",
    "estimatedRPM": "$1.05"
  }
}

Serve ad

Get an ad matched to page content. Used by the embed script.

GET /api/ads/serve?tool={slug}&tags={csv}&slot={type}&site={id}
Params:
  • tool — tool slug from known contexts (optional)
  • tags — comma-separated content tags (optional, overrides tool)
  • slot — ad placement: in-content, sidebar, banner, floating-bl, floating-br, top-banner
  • site — publisher site ID
Response:
JSON
{
  "ad": {
    "id": "string",
    "headline": "string",
    "body": "string",
    "ctaText": "string",
    "ctaUrl": "string (click redirect URL)",
    "advertiser": {
      "id": "string",
      "name": "string",
      "logo": "string",
      "logoType": "logomark | full",
      "brandColor": "string"
    }
  }
}

Returns { "ad": null } if no matching ad is found.


Embed script

Add to your site's HTML:

HTML
<script async src="https://sponsoric.com/api/ads/embed"
  data-site="YOUR_SITE_ID"></script>

The script auto-discovers data-sponsoric-slot containers and renders ads.


Check advertiser campaigns

Auth required. Get all your campaigns with performance data.
GET /api/ads/advertiser-campaigns
Authorization: Bearer sk_...
Response (200):
JSON
{
  "advertisers": [{ "id": "string", "name": "string" }],
  "summary": {
    "totalBudgetCents": 10000,
    "totalSpentCents": 3500,
    "remainingCents": 6500,
    "totalImpressions": 5000,
    "totalClicks": 125,
    "ctr": 2.5,
    "activeCampaigns": 2
  },
  "campaigns": [
    {
      "id": "string",
      "advertiserId": "string",
      "advertiserName": "string",
      "headline": "string",
      "budgetCents": 5000,
      "spentCents": 1750,
      "impressions": 2500,
      "clicks": 63,
      "ctr": 2.52,
      "active": true,
      "startsAt": "string | null",
      "endsAt": "string | null",
      "tags": ["string"]
    }
  ]
}

Billing history

Auth required. Get your payment history — campaign creation payments and add-funds transactions.
GET /api/ads/billing-history
Authorization: Bearer sk_...
Response (200):
JSON
{
  "events": [
    {
      "id": 1,
      "type": "campaign_created",
      "adId": "your-product-abc123",
      "advertiserId": "your-product",
      "advertiserName": "Your Product",
      "amountCents": 10000,
      "amountFormatted": "$100.00",
      "method": "tempo",
      "reference": "0x...",
      "createdAt": "2026-04-07T12:00:00Z"
    }
  ],
  "summary": {
    "totalCents": 10000,
    "totalFormatted": "$100.00",
    "count": 1
  }
}

Types: campaign_created, funds_added. Methods: stripe, tempo. Reference is the tx hash (tempo) or Stripe session ID (stripe).


Manage ads

Auth required. Create, update, delete, pause, or resume ads on your advertiser account.
POST /api/ads/manage
Authorization: Bearer sk_...
Actions:

Create a new ad:

JSON
{
  "action": "create-ad",
  "advertiserId": "string (optional, defaults to your first advertiser)",
  "id": "string",
  "headline": "string",
  "body": "string",
  "ctaText": "string",
  "ctaUrl": "string",
  "tags": ["string"],
  "budgetCents": 5000,
  "fundedVia": "stripe | tempo (optional, defaults to most recent ad's source)",
  "startsAt": "ISO date (optional)",
  "endsAt": "ISO date (optional)"
}

Update an ad:

JSON
{ "action": "update-ad", "id": "ad-id", "headline": "New headline", "tags": ["new-tag"] }

Pause, resume, or delete:

JSON
{ "action": "pause-ad", "id": "ad-id" }
{ "action": "resume-ad", "id": "ad-id" }
{ "action": "delete-ad", "id": "ad-id" }


Publisher earnings

Auth required. Check earnings across all your publisher sites.
GET /api/ads/publisher-earnings
Authorization: Bearer sk_...
Response (200):
JSON
{
  "sites": [
    {
      "publisherId": "string",
      "siteName": "string",
      "earnedCents": 2500,
      "earnedCentsStripe": 1800,
      "earnedCentsTempo": 700,
      "payoutMethods": { "stripeConnect": false, "tempoWallet": true },
      "payableCents": 700,
      "minimumPayoutCents": 1000,
      "payable": false,
      "lastPayoutAt": "string | null"
    }
  ],
  "summary": {
    "totalEarnedCents": 2500,
    "totalPayableCents": 700
  }
}

Publisher settings

Auth required. Update your publisher payout settings.
POST /api/ads/publisher-settings
Authorization: Bearer sk_...
Request:
JSON
{ "tempoWalletAddress": "0x... or tempox..." }

Pass an empty string to clear. Returns { ok: true, tempoWalletAddress: "..." }.

Important: Make sure you have the private key for any wallet address you set. The address receives your USDC payouts, but the private key is what lets you spend or transfer those funds. If you lose the private key, the funds are permanently unrecoverable.

Stripe Connect onboarding

Auth required. Get a Stripe Connect onboarding URL for your publisher account. The publisher must open the returned URL in a browser to complete Express account setup.
POST /api/ads/stripe-connect/link
Authorization: Bearer sk_...
Request:
JSON
{ "publisherId": "string (optional, defaults to your first publisher)" }
Response (200, not yet connected):
JSON
{
  "connected": false,
  "onboardingUrl": "https://connect.stripe.com/setup/...",
  "stripeConnectAccountId": "acct_...",
  "message": "Open the onboarding URL in a browser to complete Stripe Connect setup."
}
Response (200, already connected):
JSON
{
  "connected": true,
  "stripeConnectAccountId": "acct_...",
  "message": "Stripe Connect is already set up for this publisher."
}

For browser-based onboarding (redirect flow), use GET /api/ads/stripe-connect?publisherId=X instead.


Request payout

Auth required. Trigger a payout for your earned balance.
GET /api/ads/payout
Authorization: Bearer sk_...
Response (200):
JSON
{
  "ok": true,
  "payouts": [
    { "method": "tempo", "amountCents": 1500, "txHash": "0x..." },
    { "method": "stripe_connect", "amountCents": 1800, "transferId": "tr_..." }
  ]
}
Errors:
  • Balance below $10 minimum → 400
  • No payout method configured → 400 (with held object showing what to set up)
  • Publisher not found → 404
Each earnings source pays out through its matching channel: Stripe-sourced via Stripe Connect, crypto-sourced via Tempo USDC. Configure payout methods via /api/ads/publisher-signup (pass tempoWalletAddress) or /api/ads/publisher-settings, or set up Stripe Connect in your dashboard.

Documentation API

Get documentation as raw markdown — designed for agents to discover and read docs programmatically.

GET /api/ads/docs              → index of all doc pages
GET /api/ads/docs?page={slug}  → raw markdown content
Index response:
JSON
{
  "docs": [
    { "slug": "getting-started-advertiser", "title": "Getting Started — Advertiser", "url": "...", "web": "..." }
  ]
}
Page response: Raw markdown (Content-Type: text/markdown).

Available tags

Tags for targeting. Use 3-8 per ad or site.

Developer: developer-tools, api, cloud, devops, open-source, ai-tools, machine-learning, data, analytics Creative: design, image-editing, thumbnails, ai-images, content-creation, video-creation Business: saas, productivity, project-management, e-commerce, payments, crm, automation, no-code, email Writing: text-processing, writing, seo, blogging, branding, marketing Finance: finance, business, freelancing, entrepreneurship, side-hustle Storage: file-management, cloud-storage, privacy, security Other: mobile, messaging, social-media, education, health, real-estate, feedback, user-research, product-management