Agents and API

One call gets a site its slot.

If you are an agent working on someone's website, you can set up their Placard ad slot without a browser. No key is needed to start. Confirm advertiser choices with the owner before you set them.

1. Create a link

POST/api/v1/links

No auth. Both fields are optional; pass the domain if you know it.

FieldTypeNotes
domainstringBare hostname, like yourblog.dev
emailstringThe owner's email, for payout contact
curl -X POST https://placard.blrbdigital.com/api/v1/links \
  -H "Content-Type: application/json" \
  -d '{"domain":"yourblog.dev","email":"owner@yourblog.dev"}'

Response, 201 Created:

{
  "publisher_id": "pub_k7m2qx9dfa",
  "domain": "yourblog.dev",
  "verified": false,
  "embed": {
    "script": "<script async src=\"https://placard.blrbdigital.com/ad.js\" data-placard=\"pub_k7m2qx9dfa\"></script>",
    "iframe": "<iframe src=\"https://placard.blrbdigital.com/slot/pub_k7m2qx9dfa\" ...></iframe>",
    "link": "https://placard.blrbdigital.com/slot/pub_k7m2qx9dfa"
  },
  "verify": {
    "dns_txt": { "type": "TXT", "host": "@ (or _placard)", "value": "placard-verification=pub_k7m2qx9dfa" },
    "meta_tag": "<meta name=\"placard-verification\" content=\"pub_k7m2qx9dfa\">",
    "well_known": { "path": "/.well-known/placard.txt", "contents": "pub_k7m2qx9dfa" }
  },
  "api_key": "plk_...",
  "api_key_note": "Shown once. Use as Authorization: Bearer <api_key> for this publisher.",
  "claim_url": "https://placard.blrbdigital.com/claim?token=clm_...",
  "dashboard_url": "https://placard.blrbdigital.com/dashboard?pub=pub_k7m2qx9dfa",
  "next_steps": [ "..." ]
}

Save api_key now. It is shown once. Hand claim_url to the human owner so they can attach the slot to their account.

2. Embed it

Put embed.script in the page HTML where the ad should render. It creates a sandboxed iframe and resizes itself. If scripts are not allowed, use embed.iframe.

<script async src="https://placard.blrbdigital.com/ad.js" data-placard="pub_k7m2qx9dfa"></script>

Until the domain is verified and an advertiser is chosen, the slot shows a quiet house card, so it is safe to ship right away.

3. Verify the domain

POST/api/v1/publishers/{id}/verify

We check, in order: a DNS TXT record placard-verification={id} at the apex or _placard, the file /.well-known/placard.txt containing the id, then the homepage for the embed tag or the meta tag <meta name="placard-verification" content="{id}">. If you just deployed the embed, that alone is enough.

curl -X POST https://placard.blrbdigital.com/api/v1/publishers/pub_k7m2qx9dfa/verify \
  -H "Authorization: Bearer $PLACARD_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"yourblog.dev"}'
{
  "publisher_id": "pub_k7m2qx9dfa",
  "verified": true,
  "verified_domain": "yourblog.dev",
  "verify_method": "homepage_tag",
  "verified_now": true
}

Not found yet? You get verified: false and a checks array saying what we looked at. Wait for the deploy or DNS, then retry. Limit: 12 attempts per 10 minutes.

4. Choose advertisers

GET/api/v1/marketplace
curl https://placard.blrbdigital.com/api/v1/marketplace
{
  "advertisers": [
    {
      "advertiser_id": "adv_crossover",
      "name": "Crossover Labs",
      "categories": ["Developer tools"],
      "publisher_cpm_usd": 2.8,
      "campaigns": [ { "headline": "Your next product, built fast", "...": "..." } ]
    }
  ],
  "publisher_share": 0.7
}
PUT/api/v1/publishers/{id}/advertisers

Replaces the full allow list. Requires a verified domain. Show the owner the list and get their yes first; these ads appear on their site.

curl -X PUT https://placard.blrbdigital.com/api/v1/publishers/pub_k7m2qx9dfa/advertisers \
  -H "Authorization: Bearer $PLACARD_KEY" \
  -H "Content-Type: application/json" \
  -d '{"advertiser_ids":["adv_crossover"]}'

5. Read stats

GET/api/v1/publishers/{id}/stats
curl https://placard.blrbdigital.com/api/v1/publishers/pub_k7m2qx9dfa/stats \
  -H "Authorization: Bearer $PLACARD_KEY"
{
  "publisher_id": "pub_k7m2qx9dfa",
  "days": [ { "day": "2026-09-23", "impressions": 1840, "clicks": 12, "earnings_usd": 5.15 } ]
}

Also useful: GET /api/v1/publishers/{id} for the full current state, and GET /api/v1/publishers/me.

Auth

Send Authorization: Bearer <api_key> using the plk_ key from step 1. Browser sessions use a Firebase ID token in the same header. Creating a link and reading the marketplace need no auth.

Errors and limits

Errors are JSON: {"error": "human readable message"} with a 4xx status. Limits: 20 new links per IP per hour, 300 API requests per IP per minute. CORS is open, so this works from a browser too.