Catalog endpoints
Read the marketplace catalog through the API. Categories, domains, every publisher offering with its price and delivery stats, and how to pick one publisher per domain.
The catalog endpoints return what buyers see on the Browse page: live domains, each with every eligible publisher offering. An offering is eligible when it is active and approved, its publisher is in good standing, the domain is active and, for owner listings, the domain is verified. Authentication and rate limits are described in the overview.
GET /catalog/categories
{ "categories": [ { "id": "8b5681f7-...", "name": "News & Media", "slug": "news-media" } ] }
GET /catalog/domains
Query parameters (all optional):
| Parameter | Type | Notes |
|---|---|---|
search | string | Matches the domain name or URL |
categoryId | string | From /catalog/categories |
language, country | string | Exact names as returned in the data (English, United States) |
minDr, maxDr, minDa, maxDa | 0 to 100 | Ahrefs Domain Rating, Moz Domain Authority |
minTraffic | integer | Monthly organic traffic |
serviceType | both, guest_post or link_insertion | Keep only offerings that sell that service |
maxGuestPostPrice, maxLinkInsertionPrice | number | USD, base price before our fee |
hasCompletedOrders | true | Only offerings with at least one completed order on that domain by that publisher |
minCompletedOrders | integer | Same, with a minimum count |
updatedAfter | ISO date | Only domains whose listing or offerings changed after this time (delta sync) |
sortBy | dr, da, traffic, completed or updated | Default dr |
page, limit | integers | See pagination in the overview |
Example: the proven catalog, best-delivering domains first:
curl "https://app.linkwatcher.io/api/v1/catalog/domains?hasCompletedOrders=true&sortBy=completed&limit=100&page=1" \
-H "Authorization: Bearer lw_live_YOUR_KEY"
Response (one domain shown):
{
"domains": [
{
"id": "3682f290-...",
"domainName": "bignewsnetwork.com",
"url": "https://bignewsnetwork.com",
"categoryId": "8b5681f7-...",
"category": "News & Media",
"description": "Paid guest posting on ...",
"language": "English",
"country": "United States",
"domainType": "owner",
"metrics": { "domainRating": 75, "domainAuthority": 66, "pageAuthority": 0, "trustFlow": 0, "citationFlow": 0, "organicTraffic": 20137, "referringDomains": 0, "spamScore": 3 },
"isFeatured": false,
"updatedAt": "2026-09-17T11:31:08.162Z",
"offerings": [
{
"offeringId": "cc1cc592-...",
"publisherId": "cda5e81e-...",
"domainType": "reseller",
"guestPostEnabled": true,
"guestPostPrice": 4.4,
"linkInsertionEnabled": true,
"linkInsertionPrice": 19,
"contentWritingEnabled": true,
"contentWritingIncluded": false,
"contentWritingPrice": 5,
"minWordCount": 500,
"maxWordCount": 2000,
"turnaroundTimeDays": 2,
"contentRequirements": "500 words of article",
"prohibitedNiches": [],
"allowedLinkTypes": ["dofollow"],
"maxOutboundLinks": 2,
"examplePosts": ["https://www.bignewsnetwork.com/news/..."],
"searchEngineIndexed": true,
"updatedAt": "2026-09-04T07:09:07.291Z",
"stats": {
"completedOrders": 14,
"refundedOrders": 1,
"rejectedOrders": 0,
"decidedOrders": 15,
"completionRate": 93,
"avgDeliveryDays": 4.2,
"lastCompletedAt": "2026-09-22T11:18:05.049Z"
},
"publisher": { "completionRate": 89, "score": 88.6, "completedOrders": 123, "decidedOrders": 138, "isNew": false }
}
]
}
],
"pagination": { "page": 1, "limit": 100, "total": 312, "totalPages": 4 },
"generatedAt": "2026-09-24T08:40:00.000Z"
}
Field glossary
offerings[]: one entry per publisher selling that domain. Order from the one you pick by passing itspublisherId(and the domainid) toPOST /orders. Offerings are sorted by completed orders, then guest post price.guestPostPriceandlinkInsertionPrice: the publisher's base price in USD.nullor*Enabled: falsemeans the service is not sold. Your total is the base price plus our platform fee (see orders).stats: this publisher's history on this domain.decidedOrders= completed + refunded (cancelled orders and orders still in progress are not counted).completionRate= completed / decided, as a percentage.avgDeliveryDays= average time from payment to completion.lastCompletedAt= most recent delivery.publisher: the same publisher across all their domains.scoreis a Bayesian-smoothed completion rate (0 to 100) that pulls small samples toward the platform average;isNewmeans fewer than 3 decided orders overall.domainTypeon the domain is what the listing owner declared; on an offering it says whether that publisher is the verifiedownerof the site or areseller.isFeatured: the domain currently holds a paid featured slot (it does not affect delivery).allowedLinkTypes,maxOutboundLinks,minWordCount,maxWordCount,contentRequirements,prohibitedNiches: the publisher's rules. Orders that break the word range are refused.
Picking one publisher per domain
This is the approach we recommend for a curated catalog with proof of delivery:
- Fetch with
hasCompletedOrders=true(orminCompletedOrders=2for a stricter list). - For each domain, rank
offeringsbystats.completionRate(highest first), thenstats.completedOrders(highest first), then price (lowest first). - When an offering has
stats.decidedOrdersunder 3, fall back topublisher.scoreto compare it with the others. - Keep the winner's
publisherId, the price for the service you sell,turnaroundTimeDaysand the content rules. That is all you need to display the listing and to order later.
Keeping in sync
Re-fetch daily with updatedAfter=<last sync time> to pick up price and rule changes, and re-check a domain right before ordering with GET /catalog/domains/{id}. A 404 means it is no longer available.
GET /catalog/domains/{domainId}
Same shape as one element of the list. Returns 404 not_found when the domain is not currently available.