For approved resellers and agencies. Order guest posts on our publications, send articles and follow each link from your own system, at your partner prices.
Authorization: Bearer dfk_live_…Base URL: https://api.dofollow.pro/v1 · JSON in and out · prices in USD.
curl https://api.dofollow.pro/v1/catalog?niche=tech&min_dr=30 \
-H "Authorization: Bearer $DOFOLLOW_KEY"
GET/v1/me | Your account, partner discount and rate limit. |
GET/v1/catalog | Sites you can order, with your prices. Filters: niche, min_dr, limit (max 1000). |
POST/v1/orders | Create an order. Returns it with a pay_url. |
GET/v1/orders | Your orders, newest first. Paging: limit (max 100), before_id. |
GET/v1/orders/{id} | One order with every post: status, live URL, link check. |
POST/v1/orders/{id}/items/{item_id}/article | Send the article for one post: {"title", "html"} or {"gdoc_url"}. |
curl -X POST https://api.dofollow.pro/v1/orders \
-H "Authorization: Bearer $DOFOLLOW_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: client-42-batch-7" \
-d '{
"client": "Acme Corp",
"reference": "PO-1182",
"items": [
{"site": "example-site.com", "tier": "general",
"target_url": "https://acme.com/pricing", "anchor": "acme pricing"}
]
}'
tier: general, grey or casino (casino-only sites take only casino). Default: general.client (optional) files the order under one of your clients and their white-label report. reference is your own ID, echoed in orders and webhooks.422 invalid_items listing each problem.Idempotency-Key again → the same order comes back (no duplicate).pay_url (card or PayPal). Work starts after payment. Volume prices apply at 10+ posts when lower.pending (waiting for article or payment) → writing (with the editor) → published (live_url set; link checked daily, link_ok) · or removed.
Set an https address at my.dofollow.pro/api. Events:
order.paid | Payment received; work starts. |
order.cancelled | The order was cancelled. |
item.live | A post is published. Includes live_url. |
item.link_failed | The daily check could not find your link. Repeats weekly while it stays missing; we fix these. |
{"id": "evt_…", "type": "item.live", "created": "2026-10-21T10:00:00+00:00",
"data": {"order_id": 51, "item_id": 133, "reference": "PO-1182", "site": "example-site.com",
"live_url": "https://example-site.com/…", "published_at": "…"}}
Header X-DoFollow-Signature: t=<unix time>,v1=<hex>, where v1 is HMAC-SHA256 of "<t>." + raw body with your signing secret. Reject old timestamps (e.g. over 5 minutes) and use a constant-time compare.
import hmac, hashlib, time
def valid(secret, header, body: bytes):
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > 300: return False
mac = hmac.new(secret.encode(), f"{parts['t']}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(mac, parts["v1"])
Reply with any 2xx within 10 seconds. Otherwise we retry after 1 min, 5 min, 30 min, 2 h, 6 h and 12 h (8 attempts in all). Redirects are not followed. Events may arrive more than once or out of order: use id to de-duplicate.
120 requests a minute per key · 30 new orders an hour · 200 posts per order · 200 KB per article.
Errors look like {"error": {"code": "…", "message": "…"}} with status 400, 401 (bad key), 403 (not a partner), 404, 409 (post already published), 413, 422 or 429.
DoFollow.pro is a brand of iPressly LLC.