- Sells as: the
affiliate product (a product-scoped API key). This capability has no separate product-face contract — its public product route reuses the capability contract below; see the Edge route table's Product face row.
Shared affiliate capability. Program registry (the domain seeds its networks/tags) + byte-identical affiliate-link HTML injection into article bodies (headline-protected, word-boundary, max-links capped, FTC-disclosed) + click tracking with attribution + a performance report + the disclosure mechanism. Recording a click EMITS an affiliate event that the revenue-tracking sibling ledgers — affiliate never writes the cross-provider revenue ledger.
- Group: Commerce & revenue
- Contract:
contracts/affiliate/v1/openapi.yaml
- Console: Manage the
affiliate product in the console →
- Runbook: operational checklist for
affiliate — internal (Vagary Labs ops; not part of this public site): docs/runbooks/capability-operations.md#affiliate
- Public base:
https://api.vagarylabs.com (the consolidated API gateway — one host, per-brand sibling api.<zone>)
- Auth: a product API key (
vgk_…) issued from the console — Authorization: Bearer vgk_…
- Product face (customer-keyed):
https://api.vagarylabs.com/product/v1/affiliate/click
Edge route table
The routes this capability actually serves on the public edge — live-synced from GET https://api.vagarylabs.com/product/v1/_meta/catalog (snapshot v1). The metric is the request-granularity billing counter; the scope is the key permission required.
Product face (customer-keyed)
| Method | Path | Metric | Scope |
|---|
POST | /product/v1/affiliate/click | affiliate_clicks | write |
Endpoints
| Method | Path | Summary |
|---|
POST | /v1/programs | Register/seed an affiliate program (the DOMAIN seed point) — org-scoped, idempotent on (organization_id, program_key). The network name, base_url template, tag and keywords are STORED (never hardcoded in the capability); the Amazon tag indexofnews-20 etc. enter here. |
| | |
GET | /v1/programs | List the org's affiliate programs (active-filtered), engine-shaped (id/name/keywords/active) |
POST | /v1/inject | Inject affiliate links into article HTML — the byte-identical serving-path transform. Scans body text (never headlines) for keyword matches against the org's active programs and wraps the first max_links with affiliate anchors; returns {html, injected_count, disclosure}. Generated links are recorded best-effort for attribution. |
| | |
POST | /v1/click | Record an affiliate link click — persists to the org's click store + emits to the revenue sibling |
GET | /v1/report | Affiliate performance report — total clicks + per-affiliate_id breakdown + by-program attribution |
GET | /v1/disclosure | The canonical FTC affiliate disclosure text (a static mechanism string; not org-scoped) |
GET | /health | liveness + store/tenancy posture |
GET | /metrics | Prometheus exposition |
Schemas
ProgramCreate
| Field | Type | Description |
|---|
organization_id | string | end-customer tenant (I6); resolved/verified server-side, never trusted raw |
program_key | string | stable program id (e.g. amazon_associates) — feeds the deterministic link_id hash |
name | string | |
base_url | string | link template with {query} and {tag} placeholders |
tag | string | affiliate tag (e.g. indexofnews-20) — DOMAIN value the caller supplies; never hardcoded |
keywords | array | |
active | boolean | |
sort_order | integer | injection iteration order (deterministic) |
Program
| Field | Type | Description |
|---|
program_id | string | |
organization_id | string | |
id | string | the program_key (engine-shaped) |
name | string | |
base_url | string | |
tag | string | |
keywords | array | |
active | boolean | |
sort_order | integer | |
InjectRequest
| Field | Type | Description |
|---|
organization_id | string | |
article_html | string | the article body HTML to inject affiliate links into |
max_links | integer | domain caller may pass its own cap; default 5 (ported from the engine) |
InjectResult
| Field | Type | Description |
|---|
html | string | the article HTML with affiliate anchors injected (byte-identical to the platform engine) |
injected_count | integer | |
disclosure | string | FTC disclosure when >=1 link injected, else null |
ClickRequest
| Field | Type | Description |
|---|
organization_id | string | |
affiliate_id | string | the hashed link id (data-affiliate-id) — resolves to a program via the links store |
article_id | string | |
user_id | string | |
Error
| Field | Type | Description |
|---|
error | string | stable machine code (e.g. validation_error, not_found, unauthorized) |
reason | string | human-readable one-line explanation (no secrets/PII) |
detail | object | |
request_id | string | |
Generated by scripts/gen-capability-docs.py from contracts/affiliate/v1/openapi.yaml — the contract IS the source of truth; edit the contract, not this page. The Edge route table section is synced from the live edge catalog snapshot (v1) — re-sync with python3 scripts/sync-edge-catalog.py.