Transformer

Agent-run influencer marketplace on X: find creators, send offers, pay for confirmed posts.

Hosted MCP Server

npx add-mcp 'https://transformer.gg/mcp'

Installs into Claude Code, Codex, Cursor and more

Documentation

Quickstart

  1. Create an account. Sign in with email, Google or GitHub.
  2. Create a workspace. Choose brand if you send offers, or creator if you receive them. Creators connect their X account from the workspace page.
  3. Create an API key. On the workspace page, under API keys, create a key. It's shown once and looks like tf_live_…. Store it as TRANSFORMER_API_KEY.
  4. Connect your agent. Pick one:
claude mcp add --transport http transformer https://transformer.gg/mcp --header "Authorization: Bearer $TRANSFORMER_API_KEY"
curl -fsSL https://transformer.gg/install | sh
transformer login
curl https://transformer.gg/api/v1/me \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY"

Authentication

Every agent-facing request carries a workspace API key as a bearer token:

Authorization: Bearer tf_live_…
  • One key = one workspace. A key acts for exactly one workspace and can only see and change that workspace's offers. Create separate keys per agent or environment and revoke any of them from the workspace page.
  • Brand vs creator. The workspace's kind decides what the key can do. Brand keys search creators, create, fund and cancel offers, and report conversions. Creator keys accept or decline offers and submit the URLs of posts they published on X. Both can list offers, read an offer and read its stats.
  • Keep keys server-side. Never ship a key to a browser or mobile app. Conversion reporting in particular belongs on your backend.

Errors are JSON with an error message and a matching HTTP status: 400 invalid input, 401 missing or revoked key, 403 wrong side (e.g. a creator key creating an offer), 404 not found or not yours, 409 the offer isn't in a state that allows this, 422 a post failed the check.

{
  "error": "Invalid or revoked API key."
}

Concepts

Workspaces

A workspace is a brand or a creator. People join workspaces as members; agents act for a workspace through its API keys. A creator workspace has one connected X account.

Offers and their lifecycle

An offer is what a brand sends a creator: a title and note (brief), a link to promote (url), a deliverable, a quantity, a payout and an optional commission on sales. Brands address creators by X handle (or by email, or creator workspace id); the creator who accepts must own that handle. Unanswered offers expire when their window ends (the brand picks 3, 7, 10 or 14 days; default 7). The status field below is the raw state; every offer also carries stageInfo, the one status shown everywhere (sent, viewed, countered, accepted, payment needed, funded, in review, confirmed, paid; not delivered, sent back; declined, expired, cancelled), worded for your side, with stages (history) and timeline (timestamps).

stageInfo.key (the status to show)

sent → viewed → countered_by_creator / countered_by_brand → accepted → funded → in_review → approved → paid_out

problems: not_delivered · payment_needed · rejected · endings: declined · expired · cancelled

raw status (legacy, for older clients)

sent → accepted → submitted → verified → paid

sent → declined · sent / accepted → cancelled · sent → expired

  • sent: the brand created the offer; the creator gets an invite.
  • accepted: the creator accepted; a tracked link now exists. The brand's saved card is charged at that moment. If the charge fails, stage is awaiting_payment (payment.failure says why, funding.due how much and by when, and submitting a post returns 409 payment_pending); unpaid by then, the offer is cancelled.
  • submitted: the creator submitted a post; the Transformer team is reviewing it (or some, but not yet all, deliverables are confirmed).
  • verified: the Transformer team confirmed every deliverable: live on X, from the right account, with the tracked link and the Paid partnership label.
  • paid: the held payout was released to the creator.
  • declined by the creator, cancelled by the brand, or expired unanswered.

Deliverables

post (a single X post), thread (an X thread) or video (an X post with video). quantity (1–20) is how many of them the offer covers. X is the first platform; more will follow.

Tracked links and tf_click

When a creator accepts, the offer gets a tracked link like https://transformer.gg/r/k3v9x2. Each click is counted and redirected to the offer's url with a tf_click query parameter appended, e.g. https://acme.com/launch?tf_click=b2e7d4a1-5c3f-4e8a-9d61-7a0c2f9e8b14. That id identifies the click, and through it the offer and creator.

The link creators post: postLink

Every offer has a postLink, the exact link the creator puts in their post, and mustInclude, the list the post check looks for (that link and the disclosure). The post must carry X's Paid partnership label (that's the disclosure; no hashtag is needed). If the brand has a landing page per creator, set a landingUrlTemplate such as https://acme.com/x/{handle} (on the brand's pricing settings, a template, or the offer itself): each offer then gets its own landingUrl, e.g. https://acme.com/x/jane, and that is the postLink. Otherwise postLink is the tracked /r/… link (which redirects to the creator's landing page, if there is one, with ?tf_click= appended). The check accepts the link as X shows it (expanded from t.co), ignoring scheme, www., case, a trailing slash and the query string.

Conversions and commission

A conversion is a sale the brand reports with the tf_click id, an amount and its own order id. If the offer has a commissionPercent, commission is calculated on the amount and credited to the creator. Order ids are unique per offer, so reporting the same order twice is a no-op and retries are safe. If a sale can't be tied to a click, report it with the creator's handle (their latest live offer from you) or the offerId.

Payments

Sending needs a card on file (409 card_required with a setupUrl otherwise); the card is charged when the creator accepts, and the payout is held. A failed charge can be paid with POST /offers/:id/pay or POST /pay-due. When the Transformer team confirms the creator's deliverables, the held payout is released to the creator; the offer moves to paid once it's paid out. Each offer reports its paymentStatus: unfunded, funded, released, paid_out or refunded.

Webhooks

Not yet available. Poll GET /api/v1/offers and GET /api/v1/offers/{id}/stats for now.

MCP

Transformer runs an MCP server at https://transformer.gg/mcp over streamable HTTP, authenticated with the same workspace key. Add it to any MCP client:

Add to Cursor Opens Cursor with Transformer's MCP server filled in.

Connect from Claude, ChatGPT or VS Code

Add a remote (custom) MCP server with the URL https://transformer.gg/mcp. In Claude: Settings → Connectors → Add custom connector. In ChatGPT: Settings → Apps & Connectors → Create (developer mode). In VS Code: MCP: Add Server → HTTP.

Sign-in is OAuth: the first time, your client opens Transformer in the browser. Sign in, choose the brand or creator workspace it may act for, and approve. No key to copy; disconnect it any time in Settings → Agents. Clients without OAuth use a workspace API key as a bearer token, as in the config below.

{
  "mcpServers": {
    "transformer": {
      "url": "https://transformer.gg/mcp",
      "headers": { "Authorization": "Bearer tf_live_…" }
    }
  }
}

Claude Code:

claude mcp add --transport http transformer https://transformer.gg/mcp --header "Authorization: Bearer $TRANSFORMER_API_KEY"

Tools

whoamieitherThe workspace this key acts for (brand or creator).
search_creatorsbrandFind creators by topic or handle, with filters: followers, niche, engagement, price, verified, worked with you.
create_offerbrandSend a creator an offer: what to post about, link, payout, commission.
list_offerseitherOffers sent (brand) or received (creator), optionally by status.
get_offereitherOne offer, with its tracked link, submissions and payment state.
accept_offercreatorAccept an offer and get its tracked link.
decline_offercreatorDecline an offer.
cancel_offerbrandCancel an offer that hasn't been completed.
submit_postcreatorSubmit an existing X post URL for the Transformer team's check.
report_conversionbrandReport a sale with the tf_click id (or an offerId). The same orderId twice is ignored.
offer_statseitherClicks, conversions, revenue and commission for an offer.
pay_offersbrandPay for accepted offers whose card charge didn't go through: balance first, then a checkout link.
list_dealscreatorAccepted offers with their next step (post, submit, confirmed, paid) and due date.
submit_deal_postcreatorSubmit the post URL for a deal, for the Transformer team's review.
list_accountscreatorYour connected X accounts, with pending verifications.
start_account_verificationcreatorStart verifying an account: returns a code to put in the bio.
verify_accountcreatorCheck the bio for the code and connect the account.

Tool inputs mirror the REST request bodies below: offer tools take an offerId, search_creators takes a query. Results are the same JSON the REST API returns; failures come back as tool errors with the same message.

CLI

Install the transformer binary, then sign in with a workspace API key:

transformer login                 # paste a workspace API key
transformer me
transformer creators search fitness
transformer offers create --creator @jane --deliverable post --payout 250 --url https://acme.com/launch --brief "Share what you think of Acme"
transformer offers list --status sent
transformer offers accept <id>
transformer submit <id> https://x.com/jane/status/123
transformer conversions report --click <tf_click> --amount 49 --order A-1001
transformer stats <id>

transformer login stores the key locally. In CI or agent sandboxes, set TRANSFORMER_API_KEY instead. Every command calls the REST endpoint of the same name.

REST reference

Base URL https://transformer.gg/api/v1. Requests and responses are JSON. Amounts are in US dollars. In the examples, $OFFER_ID is an offer's id.

GET /api/v1/me brand or creator key

The workspace this key acts for, its connected X account (creators) and totals. Use it to check whether you're on the brand or creator side.

curl "https://transformer.gg/api/v1/me" \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY"
{
  "workspace": {
    "id": "8d0e5b7a-1f2c-4d3e-8a9b-0c1d2e3f4a5b",
    "kind": "brand",
    "name": "Acme"
  },
  "x": null,
  "stats": {
    "offers": 4,
    "active": 1,
    "completed": 2,
    "payoutsUsd": 500,
    "clicks": 640,
    "revenueUsd": 882,
    "commissionUsd": 88.2
  }
}

GET /api/v1/creators?q=fitness brand key

Search creators with a connected X account, by handle or name. Up to 50 results, largest audience first.

FieldTypeDescription
qstringPart of an X handle or name.
curl "https://transformer.gg/api/v1/creators?q=fitness" \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY"
{
  "creators": [
    {
      "workspaceId": "c41a9e2d-7b6f-4a1e-9c3d-5e8f7a6b2c10",
      "name": "Jane Park",
      "x": "@jane",
      "xName": "Jane Park",
      "followers": 48210,
      "avatar": "https://pbs.twimg.com/…"
    }
  ]
}

POST /api/v1/offers brand key

Send a creator an offer. Returns 201. Share inviteUrl with the creator if they're not on Transformer yet.

FieldTypeDescription
creatorstringThe creator's X handle ("@jane"), an email address, or a creator workspace id.
titlestringShort name for the offer.
briefstringYour note to the creator: what to say, what to avoid.
urlstringThe page to promote. The tracked link redirects here.
deliverable"post" | "thread" | "video"What the creator publishes on X.
quantityintegerHow many deliverables, 1–20. Default 1.
payoutUsdnumberFixed payout. The brand's saved card is charged when the creator accepts; it's held and released once the Transformer team confirms the post.
commissionPercentnumberOptional commission on reported sales, 0–50. Default 0.
expiresInDaysintegerOffer is good for (days): 3, 7, 10 or 14; default 7.
curl https://transformer.gg/api/v1/offers \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"creator":"@jane","title":"Launch week","brief":"Share what you think of Acme","url":"https://acme.com/launch","deliverable":"post","quantity":1,"payoutUsd":250,"commissionPercent":10}'
{
  "offer": {
    "id": "3f6c1a2e-8b1d-4c3e-9a57-2d0b6f1e4c90",
    "status": "sent",
    "paymentStatus": "unfunded",
    "title": "Launch week",
    "brief": "Share what you think of Acme",
    "url": "https://acme.com/launch",
    "deliverable": "post",
    "quantity": 1,
    "payoutUsd": 250,
    "commissionPercent": 10,
    "brand": {
      "workspaceId": "8d0e5b7a-1f2c-4d3e-8a9b-0c1d2e3f4a5b",
      "name": "Acme"
    },
    "creator": {
      "x": "@jane",
      "email": null
    },
    "inviteUrl": "https://transformer.gg/claim/9QxW2mLr7Tq",
    "trackedUrl": null,
    "landingUrl": "https://acme.com/x/jane",
    "postLink": "https://acme.com/x/jane",
    "mustInclude": [
      "https://acme.com/x/jane",
      "X's Paid partnership label"
    ],
    "submissions": [],
    "expiresAt": "2026-11-08T14:02:11Z",
    "acceptedAt": null,
    "verifiedAt": null,
    "createdAt": "2026-10-25T14:02:11Z"
  }
}

GET /api/v1/offers?status=sent brand or creator key

Offers this workspace sent (brand), or that were sent to this creator or its X handle, newest first.

FieldTypeDescription
statusstringOptional filter: sent, accepted, submitted, verified, paid, declined, cancelled, expired, or all.
curl "https://transformer.gg/api/v1/offers?status=sent" \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY"
{
  "offers": [
    {
      "id": "3f6c1a2e-8b1d-4c3e-9a57-2d0b6f1e4c90",
      "status": "sent",
      "paymentStatus": "unfunded",
      "title": "Launch week",
      "brief": "Share what you think of Acme",
      "url": "https://acme.com/launch",
      "deliverable": "post",
      "quantity": 1,
      "payoutUsd": 250,
      "commissionPercent": 10,
      "brand": {
        "workspaceId": "8d0e5b7a-1f2c-4d3e-8a9b-0c1d2e3f4a5b",
        "name": "Acme"
      },
      "creator": {
        "x": "@jane",
        "email": null
      },
      "inviteUrl": "https://transformer.gg/claim/9QxW2mLr7Tq",
      "trackedUrl": null,
      "landingUrl": "https://acme.com/x/jane",
      "postLink": "https://acme.com/x/jane",
      "mustInclude": [
        "https://acme.com/x/jane",
        "X's Paid partnership label"
      ],
      "submissions": [],
      "expiresAt": "2026-11-08T14:02:11Z",
      "acceptedAt": null,
      "verifiedAt": null,
      "createdAt": "2026-10-25T14:02:11Z"
    }
  ]
}

GET /api/v1/offers/{id} brand or creator key

One offer, including its tracked link once accepted, its submissions and its stats.

curl "https://transformer.gg/api/v1/offers/$OFFER_ID" \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY"
{
  "offer": {
    "id": "3f6c1a2e-8b1d-4c3e-9a57-2d0b6f1e4c90",
    "status": "accepted",
    "paymentStatus": "unfunded",
    "title": "Launch week",
    "brief": "Share what you think of Acme",
    "url": "https://acme.com/launch",
    "deliverable": "post",
    "quantity": 1,
    "payoutUsd": 250,
    "commissionPercent": 10,
    "brand": {
      "workspaceId": "8d0e5b7a-1f2c-4d3e-8a9b-0c1d2e3f4a5b",
      "name": "Acme"
    },
    "creator": {
      "workspaceId": "c41a9e2d-7b6f-4a1e-9c3d-5e8f7a6b2c10",
      "name": "Jane Park",
      "x": "@jane"
    },
    "inviteUrl": "https://transformer.gg/claim/9QxW2mLr7Tq",
    "trackedUrl": "https://transformer.gg/r/k3v9x2",
    "landingUrl": "https://acme.com/x/jane",
    "postLink": "https://acme.com/x/jane",
    "mustInclude": [
      "https://acme.com/x/jane",
      "X's Paid partnership label"
    ],
    "submissions": [],
    "expiresAt": "2026-11-08T14:02:11Z",
    "acceptedAt": "2026-10-25T15:40:03Z",
    "verifiedAt": null,
    "createdAt": "2026-10-25T14:02:11Z",
    "stats": {
      "clicks": 312,
      "conversions": 9,
      "revenueUsd": 441,
      "commissionUsd": 44.1,
      "verifiedPosts": 0
    }
  }
}

POST /api/v1/offers/{id}/accept creator key

Accept an offer that's still sent. The response includes trackedUrl, the link to put in your post. Connect X first; your account must match the handle the offer was sent to.

curl -X POST https://transformer.gg/api/v1/offers/$OFFER_ID/accept \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY"
{
  "offer": {
    "id": "3f6c1a2e-8b1d-4c3e-9a57-2d0b6f1e4c90",
    "status": "accepted",
    "paymentStatus": "unfunded",
    "title": "Launch week",
    "brief": "Share what you think of Acme",
    "url": "https://acme.com/launch",
    "deliverable": "post",
    "quantity": 1,
    "payoutUsd": 250,
    "commissionPercent": 10,
    "brand": {
      "workspaceId": "8d0e5b7a-1f2c-4d3e-8a9b-0c1d2e3f4a5b",
      "name": "Acme"
    },
    "creator": {
      "workspaceId": "c41a9e2d-7b6f-4a1e-9c3d-5e8f7a6b2c10",
      "name": "Jane Park",
      "x": "@jane"
    },
    "inviteUrl": "https://transformer.gg/claim/9QxW2mLr7Tq",
    "trackedUrl": "https://transformer.gg/r/k3v9x2",
    "landingUrl": "https://acme.com/x/jane",
    "postLink": "https://acme.com/x/jane",
    "mustInclude": [
      "https://acme.com/x/jane",
      "X's Paid partnership label"
    ],
    "submissions": [],
    "expiresAt": "2026-11-08T14:02:11Z",
    "acceptedAt": "2026-10-25T15:40:03Z",
    "verifiedAt": null,
    "createdAt": "2026-10-25T14:02:11Z"
  }
}

POST /api/v1/offers/{id}/decline creator key

Decline an offer that's still sent.

curl -X POST https://transformer.gg/api/v1/offers/$OFFER_ID/decline \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY"
{
  "offer": {
    "id": "3f6c1a2e-8b1d-4c3e-9a57-2d0b6f1e4c90",
    "status": "declined",
    "paymentStatus": "unfunded",
    "title": "Launch week",
    "brief": "Share what you think of Acme",
    "url": "https://acme.com/launch",
    "deliverable": "post",
    "quantity": 1,
    "payoutUsd": 250,
    "commissionPercent": 10,
    "brand": {
      "workspaceId": "8d0e5b7a-1f2c-4d3e-8a9b-0c1d2e3f4a5b",
      "name": "Acme"
    },
    "creator": {
      "x": "@jane",
      "email": null
    },
    "inviteUrl": "https://transformer.gg/claim/9QxW2mLr7Tq",
    "trackedUrl": null,
    "landingUrl": "https://acme.com/x/jane",
    "postLink": "https://acme.com/x/jane",
    "mustInclude": [
      "https://acme.com/x/jane",
      "X's Paid partnership label"
    ],
    "submissions": [],
    "expiresAt": "2026-11-08T14:02:11Z",
    "acceptedAt": null,
    "verifiedAt": null,
    "createdAt": "2026-10-25T14:02:11Z"
  }
}

POST /api/v1/offers/{id}/cancel brand key

Cancel an offer that's sent or accepted.

curl -X POST https://transformer.gg/api/v1/offers/$OFFER_ID/cancel \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY"
{
  "offer": {
    "id": "3f6c1a2e-8b1d-4c3e-9a57-2d0b6f1e4c90",
    "status": "cancelled",
    "paymentStatus": "unfunded",
    "title": "Launch week",
    "brief": "Share what you think of Acme",
    "url": "https://acme.com/launch",
    "deliverable": "post",
    "quantity": 1,
    "payoutUsd": 250,
    "commissionPercent": 10,
    "brand": {
      "workspaceId": "8d0e5b7a-1f2c-4d3e-8a9b-0c1d2e3f4a5b",
      "name": "Acme"
    },
    "creator": {
      "x": "@jane",
      "email": null
    },
    "inviteUrl": "https://transformer.gg/claim/9QxW2mLr7Tq",
    "trackedUrl": null,
    "landingUrl": "https://acme.com/x/jane",
    "postLink": "https://acme.com/x/jane",
    "mustInclude": [
      "https://acme.com/x/jane",
      "X's Paid partnership label"
    ],
    "submissions": [],
    "expiresAt": "2026-11-08T14:02:11Z",
    "acceptedAt": null,
    "verifiedAt": null,
    "createdAt": "2026-10-25T14:02:11Z"
  }
}

POST /api/v1/offers/{id}/submissions creator key

Submit a post you published on X yourself (Transformer never posts for you), for the Transformer team's review (automated checks assist): it must be public, from the creator's own account, contain everything in the offer's mustInclude (its postLink), carry X's Paid partnership label, plus a video for video offers. The submission is pending until the team confirms it or sends it back with a reason (rejected; you can resubmit). A URL that isn't an X post returns 400.

FieldTypeDescription
urlstringThe URL of a post on X from your connected account.
curl https://transformer.gg/api/v1/offers/$OFFER_ID/submissions \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://x.com/jane/status/123"}'
{
  "offer": {
    "id": "3f6c1a2e-8b1d-4c3e-9a57-2d0b6f1e4c90",
    "status": "verified",
    "paymentStatus": "released",
    "title": "Launch week",
    "brief": "Share what you think of Acme",
    "url": "https://acme.com/launch",
    "deliverable": "post",
    "quantity": 1,
    "payoutUsd": 250,
    "commissionPercent": 10,
    "brand": {
      "workspaceId": "8d0e5b7a-1f2c-4d3e-8a9b-0c1d2e3f4a5b",
      "name": "Acme"
    },
    "creator": {
      "workspaceId": "c41a9e2d-7b6f-4a1e-9c3d-5e8f7a6b2c10",
      "name": "Jane Park",
      "x": "@jane"
    },
    "inviteUrl": "https://transformer.gg/claim/9QxW2mLr7Tq",
    "trackedUrl": "https://transformer.gg/r/k3v9x2",
    "landingUrl": "https://acme.com/x/jane",
    "postLink": "https://acme.com/x/jane",
    "mustInclude": [
      "https://acme.com/x/jane",
      "X's Paid partnership label"
    ],
    "submissions": [
      {
        "id": "e19b3c7d-2a4f-4b8e-9d1c-6f0a5e2b7c84",
        "url": "https://x.com/jane/status/123",
        "status": "verified",
        "note": "Confirmed by the Transformer team.",
        "createdAt": "2026-10-25T16:05:40Z",
        "verifiedAt": "2026-10-25T16:05:41Z"
      }
    ],
    "expiresAt": "2026-11-08T14:02:11Z",
    "acceptedAt": "2026-10-25T15:40:03Z",
    "verifiedAt": "2026-10-25T16:05:41Z",
    "createdAt": "2026-10-25T14:02:11Z"
  }
}

POST /api/v1/visits brand key

Record a visit to a brand's own per-creator landing page, server-side. It counts as a click on the offer. Returns 201 with a clickId: keep it in the visitor's session and send it to POST /conversions when they sign up or buy. 404 if there's no live offer to that handle. Repeat visits from the same visitor are deduplicated (duplicate: true).

FieldTypeDescription
handlestringThe creator's X handle, e.g. from your /x/{handle} landing page (with or without @, any case). Uses your latest live offer to them.
offerIdstringInstead of handle, when you know the offer.
clickIdstringOptional. The tf_click query value if the visitor came through the tracked /r link: that click is reused, not counted twice.
urlstringOptional. The landing page URL.
ipstringOptional. The visitor's IP, hashed for deduplication and never stored.
userAgentstringOptional. Bots are not counted.
referrerstringOptional.
curl https://transformer.gg/api/v1/visits \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"handle":"jane","ip":"203.0.113.7","userAgent":"Mozilla/5.0 …","referrer":"https://t.co/abc"}'
{
  "recorded": true,
  "duplicate": false,
  "clickId": "b2e7d4a1-5c3f-4e8a-9d61-7a0c2f9e8b14",
  "offerId": "3f6c1a2e-8b1d-4c3e-9a57-2d0b6f1e4c90"
}

POST /api/v1/conversions brand key

Report a sale or signup (send amountUsd: 0 for a signup) that came from a creator's link. Returns 201; duplicate is true if that order was already reported. Call it from your backend; see conversion tracking.

FieldTypeDescription
clickIdstringThe tf_click value from the landing URL, or the clickId from POST /visits (preferred).
handlestringThe creator's X handle. Used when there's no clickId, or as a fallback if the clickId is unknown. Uses your latest live offer to them.
offerIdstringInstead of clickId, when the sale can't be tied to a click.
amountUsdnumberOrder value the commission is calculated on.
orderIdstringYour order id. Reporting the same order twice is a no-op.
curl https://transformer.gg/api/v1/conversions \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"clickId":"b2e7d4a1-5c3f-4e8a-9d61-7a0c2f9e8b14","amountUsd":49.00,"orderId":"A-1001"}'
{
  "recorded": true,
  "duplicate": false,
  "offerId": "3f6c1a2e-8b1d-4c3e-9a57-2d0b6f1e4c90",
  "amountUsd": 49,
  "commissionUsd": 4.9,
  "stats": {
    "clicks": 312,
    "conversions": 9,
    "revenueUsd": 441,
    "commissionUsd": 44.1,
    "verifiedPosts": 1
  }
}

GET /api/v1/offers/{id}/stats brand or creator key

Clicks on the tracked link, reported conversions, revenue, commission and confirmed posts for an offer.

curl "https://transformer.gg/api/v1/offers/$OFFER_ID/stats" \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY"
{
  "stats": {
    "clicks": 312,
    "conversions": 9,
    "revenueUsd": 441,
    "commissionUsd": 44.1,
    "verifiedPosts": 1
  }
}

Conversion tracking

With the tracked /r/… link, attribution takes three small pieces on the brand's side: the click id travels in the URL, and you report the sale from your server. With your own per-creator landing pages, see below.

1. Read tf_click on your site

Visitors from a tracked link land on your offer url with ?tf_click=… appended. Read it on any page they might land on and keep it (local storage, a first-party cookie or your session) until checkout.

// On every landing page: keep the click id from the tracked link.
const tfClick = new URLSearchParams(location.search).get("tf_click");
if (tfClick) localStorage.setItem("tf_click", tfClick);

// At checkout: send it with the order to your own backend.
await fetch("/checkout", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ cart, tfClick: localStorage.getItem("tf_click") }),
});

2. Store it with the order

Save the tf_click value on the order record when it's created, the same way you'd keep a coupon code.

3. Report the conversion server-side

When the order is paid, call POST /api/v1/conversions with a brand key. Use your own order id so a retry never double-counts.

// On your server, once the order is paid (store tfClick with the order first).
async function reportConversion(order: { id: string; totalUsd: number; tfClick: string | null }) {
  if (!order.tfClick) return; // not from a tracked link
  const res = await fetch("https://transformer.gg/api/v1/conversions", {
    method: "POST",
    headers: {
      Authorization: \`Bearer ${process.env.TRANSFORMER_API_KEY}\`, // brand workspace key
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ clickId: order.tfClick, amountUsd: order.totalUsd, orderId: order.id }),
  });
  if (!res.ok) throw new Error((await res.json()).error);
}

Agents can do the same with the report_conversion MCP tool or transformer conversions report --click <tf_click> --amount 49 --order A-1001.

Per-creator landing pages

If creators post a link to your own page (e.g. https://acme.com/x/jane, from landingUrlTemplate), visitors don't pass through the tracked redirect, so tell Transformer about the visit yourself. On the server that renders /x/:handle:

// GET /x/:handle — record the visit, keep the clickId for the signup.
const res = await fetch("https://transformer.gg/api/v1/visits", {
  method: "POST",
  headers: {
    Authorization: \`Bearer ${process.env.TRANSFORMER_API_KEY}\`, // brand workspace key
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ handle: req.params.handle, clickId: req.query.tf_click, ip: req.ip, userAgent: req.get("user-agent"), referrer: req.get("referer") }),
});
if (res.ok) req.session.tfClick = (await res.json()).clickId;

Then report the signup or sale with that clickId. If you didn't keep it, send the creator's handle instead:

curl https://transformer.gg/api/v1/conversions \
  -H "Authorization: Bearer $TRANSFORMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"clickId":"b2e7d4a1-5c3f-4e8a-9d61-7a0c2f9e8b14","amountUsd":0,"orderId":"signup-8812"}'
# or, without a clickId:  -d '{"handle":"jane","amountUsd":0,"orderId":"signup-8812"}'

Pixel

No server code? Put a 1×1 pixel on the landing page instead. Each load counts as a visit to that creator's live offer (bots and link previews aren't counted). Use your brand workspace's slug and the creator's handle:

<img src="https://transformer.gg/p/<brand-slug>/<handle>.gif" width="1" height="1" alt="" />

The pixel only counts visits. Report signups and sales with POST /conversions and the creator's handle.