Developer docs
API reference
The Clickless Agent API, version 1. Requests and responses are JSON. The OpenAPI 3.1 description is the source of truth: download openapi.yaml.
Basics
- Base URL:
https://api.getclickless.ai. Paths start with/v1. - Auth:
Authorization: Bearer ck_live_…, a key for one agent from the developer portal. Production accepts live keys only. - Rate limit: per key, 120 requests a minute. Over it you get
429withRetry-Afterin seconds. - Every response carries
X-Request-Id, and every error body itsrequest_id. Quote it when you contact Clickless. - Retries are safe: approve and handoff are idempotent per token, and report per brand, order and agent.
Idempotency-Keyis accepted on every POST, though responses aren’t replayed from it. Retrying a search issues fresh tokens, which is harmless. - Money is integer cents with an explicit currency. Text fields must be well-formed text without control characters.
Errors
One shape everywhere:
{ "error": { "code": "token_expired", "message": "Attribution token is past its 60-day window", "request_id": "req_NUpB9LgJrk6iwEtA" }}- invalid_request400
- A field is missing, malformed, too long, or holds control characters.
- unauthorized401
- The API key is missing, wrong, revoked, or for the other environment, or it’s a live key and its agent isn’t approved for live traffic.
- agent_suspended401
- The key’s agent is suspended.
- not_found404
- No such offer, token or conversion for your agent.
- not_approved409
- Checkout handoff before the person’s approval was recorded.
- checkout_unavailable409
- The brand’s checkout can’t take this offer right now.
- token_expired410
- The attribution token is more than 60 days old. Search again.
- payload_too_large413
- The request body is over 64 KiB.
- rate_limited429
- Too many requests for this key. Wait for Retry-After seconds.
- internal_error500
- Something failed on Clickless’s side. Retry; quote the request id if it persists.
Offers
POST/v1/offers/search: Offers ranked for a shopping need. Each carries a fresh attribution token.
Request
- intentstring, 2–500 · required
- What the person wants, in their words. The need only: no names, emails, phone numbers or addresses.
- ship_to.countrystring, ISO 3166 alpha-2 · required
- The country it ships to.
- ship_to.regionstring
- State or province code.
- ship_to.postal_codestring
- Postal code.
- budget_centsinteger
- The most the person wants to spend.
- constraints.categoriesstring[]
- Limit to these categories.
- constraints.exclude_brandsstring[]
- Brands to leave out.
- constraints.age_verifiedboolean
- True only when you’ve verified the person’s age; age-gated offers need it.
- user_context.user_refstring
- Your pseudonymous id for the person, hashed with your agent’s key and never stored raw.
- limitinteger, 1–10, default 3
- Offers and stores together. Show three at most.
- include_storesboolean
- Also return whole stores in stores when products don’t fill the limit. A store has no price; its link lands on the store. Left out, it’s on for agents Clickless operates and off for yours.
- all_categoriesboolean, default false
- For agents Clickless operates: search every category, not just the agent’s own. It changes nothing for other agents.
Response: each offer
- offer_iduuid
- The offer.
- productobject
- id, title, description, images, price_cents, currency, availability, category_path.
- brandobject
- id, name, domain, and affiliated (owned by Clickless or its founder).
- price_centsinteger
- Price after the deal, before tax and shipping. The full price when the brand’s checkout takes the deal off itself.
- dealobject
- type (percent_off, fixed_off, free_shipping, bundle, subscribe_save, first_order, cpa), a summary to show as returned (it names any code the person types at checkout), and ends_at.
- commission_previewobject
- What you’d earn at this price: agent_share_cents, currency, basis (percent or cpa), and paid_by (brand, or network: your share is of what the network pays Clickless).
- trust_scorenumber, 0–1
- Neutral (0.5) for every brand today. Scoring from the brand’s fulfillment, return and dispute record comes next.
- regulated_tierboolean
- Regulated category: describe it in the brand’s words only, with no claims.
- regulated_categorystring or null
- Which one, for example health.
- no_health_claimsboolean
- The brand allows no health claims; the product description is withheld.
- sponsoredboolean
- Paid placement. Label it.
- disclosure_textstring
- Show it with the offer. Always present.
- attribution_tokenstring, 22 chars
- Attributes a sale to this search. Valid for 60 days.
- checkoutobject
- method (always link today; ACP and UCP sessions come next) and url, a go.getclickless.ai link to the brand.
GET/v1/offers/{offer_id}: One offer’s current price, deal and availability, without a token.
- product_iduuid, query
- Price against this product. Defaults to the cheapest eligible one.
- age_verifiedboolean, query
- Required true for age-gated offers.
Returns the same fields as a search offer, without attribution_token and checkout. To show it to a person, search again.
Approval and checkout
POST/v1/attribution/approve: Records that the person approved one offer. Call it only after they say yes.
- tokenstring · required
- The offer’s attribution_token.
- mandate_refstring
- AP2 mandate id, when the purchase is authorized through AP2.
- cap_centsinteger
- A spending cap the person set.
Returns token, approved_at, mandate_ref and cap_cents. The first approval stands; repeating it is safe.
POST/v1/checkout/handoff: The brand’s checkout for an approved offer.
- tokenstring · required
- An approved attribution_token.
Returns method, url, session_id (null today; reserved for ACP or UCP sessions), discount_code (your per-agent code, when the brand uses codes) and token. Before an approval it answers 409 not_approved. The brand’s checkout charges the card; Clickless never does.
Conversions
POST/v1/conversions/report: Reports an order, for integrations whose brand orders don’t reach Clickless on their own.
- tokenstring · required
- The attribution_token the order came from.
- external_order_idstring · required
- The brand’s order number, from the confirmation.
- gross_centsinteger · required
- Order total in cents.
- currencystring, ISO 4217 · required
- The order’s currency.
Answers 202 with a status: pending_match, matched, not_matched or duplicate. A report is a claim: it earns nothing unless the brand’s own records match the order.
GET/v1/conversions: Your agent’s conversions, newest order first.
- periodstring, query
- A month (2026-10) or ISO week (2026-W40), by order date. Omit for all.
- limitinteger, 1–100, default 50
- Page size.
- cursorstring
- next_cursor from the previous page.
Each conversion has conversion_id, status (matched, disputed, reversed), match_method, the brand, the order (number, gross, currency, date) and agent_net_cents, your share net of refunds so far.
GET/v1/conversions/{conversion_id}: The audit chain for one conversion, the same one the brand sees.
From the search to the payout: the query (only intent words that also appear in the product’s text), the offers shown by position, the approval, each checkout handoff and click, the order and its refunds, how it was matched, every ledger entry in signed cents, and the part of each payout that came from it. Other brands’ offers in the same search show only their position and whether they were sponsored.
Earnings and account
GET/v1/earnings: Accrued, pending, payable, in transit and paid, for one period.
- periodstring, query
- A month (2026-10) or ISO week (2026-W40). Defaults to the current month.
- currencystring, query
- Defaults to USD.
Returns period, currency, accrued_cents, pending_cents, payable_cents, available_cents (the same amount as payable_cents), in_transit_cents, paid_cents, referral_cents and next_payout_on. Earnings and payouts explains each one.
GET/v1/picks: Creators’ picks: the live offers creators approved for their own Product Experts.
- creatorstring, query
- A creator agent’s handle. Omit for every creator.
- categorystring, query
- A brand category, such as hydration, sleep, skincare or pet.
- limitinteger, 1–50, default 20
- How many picks.
Each pick has the creator (handle, name, page and verified Instagram), the brand, its category, the deal, a product to show, sponsored and disclosure_text, which you show with it. To send someone who wants a pick, use its ask_url: the creator’s own agent, which earns the creator the commission. Health and age-gated offers aren’t listed.
GET/v1/me: The agent your key belongs to.
Returns id, name, owner_type, status (sandbox, live, producing, suspended), categories and payouts_ready, true once payout setup and tax details are complete.
Product Experts for stores
POST/v1/brand-agents/provision: Drafts a store’s Product Expert from its URL, for its owner to claim. Takes a developer agent’s key.
- store_urlstring · required
- The store’s own website. Not a marketplace or site-builder address.
- brand_namestring
- The store’s name, when the site doesn’t show it clearly.
- contact_emailstring
- Only when the store’s owner asked for the claim link by email. One email; the address isn’t kept.
Returns the draft: preview_url (private, marked Preview), claim_url for the store’s owner, product_expert with its handle for the widget, what was learned, the final check (test) run in sandbox, pricing to relay word for word and next_steps. 201 when created; 200 with the store’s existing draft, so calling again checks on the test. The draft isn’t public, sends no messages and earns nothing until its owner claims it with proof of control. Errors: 403 not a developer key, 409 already on Clickless, 422 refused, 429 the key’s 20 new stores a day, 503 the day’s spend limit. Add a Product Expert to a store walks through it.