REST API
Everything the dashboard does, over HTTPS with an API key.
Authentication
Create a key in Settings → API keys and send it as a bearer token. Keys are shown once.
curl https://api.adjoin.dev/v1/me \
-H "Authorization: Bearer adj_live_…"- read
- GET requests.
- write
- Create and change campaigns, sites and placements.
- conversions
- Only the server-to-server conversion endpoints.
A key is never an admin, and cannot create keys or request payouts — those need a signed-in person.
Money is always an integer in micros: 1 USD = 1,000,000.
Endpoints
- GET /v1/me
- Who the key belongs to.
- GET /v1/campaigns
- Your campaigns with status, bid, budget and spend.
- POST /v1/campaigns
- Create a campaign; starts in review. Budget is held from your prepaid balance.
- POST /v1/campaigns/plan
- Starting bid, reach forecast and reserve for a budget, before you commit.
- GET /v1/refunds?campaign_id=cmp_…
- Clicks we filtered and did not bill, with the reason for each.
- POST /v1/conversions/s2s
- Confirm a conversion from your server.
- POST /v1/conversions/s2s/refund
- Reverse a confirmed order inside its return window.
- GET /v1/sites · POST /v1/sites
- Your sites; register a domain.
- POST /v1/sites/{site_id}/verify
- Check domain ownership (DNS TXT, file or meta tag).
- GET /v1/placements?site_id= · POST /v1/placements
- Slots on a site; create one.
- GET /v1/placements/{placement_id}/live
- Whether a slot has received requests in the last 24 hours.
- GET /v1/boost · POST /v1/boost
- Launch Day Boost status; claim it for a campaign.
- GET /v1/credits
- Cross-promotion credit balance and recent activity.
- GET /v1/segments
- Audience labels publishers have set, with 7-day pageviews (only labels with 100+). Use them in target_segments / exclude_segments when creating a campaign.
Create a campaign
pricing_model is one of cpc, cpm, cpa, affiliate, guaranteed or cross_promo (paid in credit, no cash budget). A 402 means your available balance is too low.
curl -X POST https://api.adjoin.dev/v1/campaigns \
-H "Authorization: Bearer adj_live_…" -H "Content-Type: application/json" \
-d '{
"name": "Launch",
"pricing_model": "cpc",
"bid_micros": 300000,
"total_budget_micros": 50000000,
"daily_cap_micros": 5000000,
"target_categories": ["devtools"],
"creatives": [{ "headline": "Ship faster", "body": "…", "cta": "Try it",
"landing_url": "https://myapp.dev", "format": "card" }]
}'Server-to-server conversions
Set the campaign’s conversion source to s2s, then confirm orders from your server with a key that has the conversions scope. The pixel stops billing for that campaign, so one order is never charged through both paths. Clicks can be confirmed for 7 days.
# the ad click lands on https://myapp.dev/?aj_t=… — keep aj_t with the order
curl -X POST https://api.adjoin.dev/v1/conversions/s2s \
-H "Authorization: Bearer adj_live_…" -H "Content-Type: application/json" \
-d '{ "click_token": "<aj_t>", "order_id": "order_1234", "value_micros": 29000000 }'
# a return or cancellation, inside the return window
curl -X POST https://api.adjoin.dev/v1/conversions/s2s/refund \
-H "Authorization: Bearer adj_live_…" -H "Content-Type: application/json" \
-d '{ "campaign_id": "cmp_…", "order_id": "order_1234" }'Errors
Errors are JSON with a detail field. 401: missing or invalid key. 403: the key lacks the scope. 404 is also returned for other accounts’ objects, so their existence is never revealed.
Questions: [email protected]