1. Create a link
No auth. Both fields are optional; pass the domain if you know it.
| Field | Type | Notes |
|---|---|---|
domain | string | Bare hostname, like yourblog.dev |
email | string | The 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
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
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
}
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
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.