# Buy links yourself

One journey from sign-up to a live, paid link. Each step shows the way in the app and the way with your AI agent, on the same account, so you can mix them. Your agent can also set you up from this page.

On self-serve you run the work: in the app, with your AI agent, or both. The app and the agent work on the same
account and the same placements, so you can mix them at any step. For example, you pick the sites in the app,
and your agent sends the articles and watches the activity feed. Or your agent finds the sites, and you approve
them in the app.

You pay each publisher directly, at the price the site shows. Linkio charges a fee per job (a search past the
free sites, an article, a check). Each step below has its own page.

For an agent that sets a person up: go to [If your agent sets you up](#self-serve-if-your-agent-sets-you-up) below. Do
part A or part B, then part C. Then the person and you work through the same steps.

## The steps

### 1. Start: account and brand

Make the account, put it on self-serve, and add your brand and the pages you want links to.

- **In the app:** sign up at https://www.linkio.com/signup. Switch the mode in the menu under your name
  (**Your Mode**). Add the brand at https://www.linkio.com/clients/new.
- **With your agent:** the agent signs you up without a browser (part A below). `account_billing_mode` reads
  and switches the mode. `client_create` adds the brand, and `target_pages_add` adds more pages.

[Start: account, brand and money](/docs/self-serve/start)

### 2. Connect your agent (optional)

Skip this step if you work only in the app. You can connect an agent at any later step: it sees the same
account, brands, orders and placements.

- **In the app:** make a key at https://www.linkio.com/account/api-keys (the **Automation** level for an agent
  that orders, sends and records payments). Or add the Linkio connector in Claude.ai or ChatGPT and sign in.
- **With your agent:** the agent connects to Linkio's MCP server with the key (part C below). An agent that
  signed you up has its key already.

[Connect an agent](/docs/agents)

### 3. Money

Linkio's fees are paid from your own provider keys, money on the account or a card. The publisher is paid
separately.

- **In the app:** add your own provider keys at https://www.linkio.com/account/ai-keys, money at
  https://www.linkio.com/shop or a card at https://www.linkio.com/billing. Set spending limits at
  https://www.linkio.com/billing#limits.
- **With your agent:** `usage_receipt` says whether paid work can start. `usage_estimate` gives a job's price
  before it runs, and `usage_limits_get` reads the limits. The person adds the keys, the money or the card, not
  the agent.

[Who you pay, and for what](/docs/self-serve/money)

### 4. Find sites

Search the inventory. Read each site's numbers, its record with Linkio and who sells it (the owner or a
reseller).

- **In the app:** open https://www.linkio.com/websites, type a topic and use the filters (**Max Cost**,
  **Seller policy**).
- **With your agent:** `website_search` searches by topic or domain. `ai_find_sites_start` runs the automated
  search.

[Find sites](/docs/self-serve/find-sites)

### 5. Order

Add the sites to an order with your target page and anchor text. An order only groups your placements; it is
never paid as a whole.

- **In the app:** on https://www.linkio.com/websites, tick the sites, select **New Order**, then
  **Create & Review Order**.
- **With your agent:** `order_create` opens the order, and `line_items_add_to_order` adds the sites.
  `line_items_update` changes a placement later.

[Order a placement](/docs/self-serve/order)

### 6. The article

Upload an article you wrote, or let Linkio's article system write it.

- **In the app:** in the order, select **Start Article** on the row of the site.
- **With your agent:** `article_gen_readiness` says whether a placement can start, and `article_gen_start`
  starts the article. `ownContent: true` on the placement marks an article you write yourself.

[Buy a placement with your own article](/docs/self-serve/own-article) or
[Linkio's article system](/docs/self-serve/linkio-article)

### 7. Send

Check the article and send it to the publisher.

- **In the app:** in the order, on the row of the site, select **Send** in the **Publisher** column, then
  **Confirm & Send**.
- **With your agent:** `workflow_verify_doc` checks the Google Doc. `workflow_send_to_publisher` with
  `checkOnly: true` shows what the send would do; the agent sends after your yes.

[Send the article and track the placement](/docs/self-serve/send-and-track)

### 8. Track

Read the publisher's replies and watch where each placement stands.

- **In the app:** the activity feed is at https://www.linkio.com/account/activity. A reply shows as new on the
  order row, and all messages are under **Messages**.
- **With your agent:** `account_activity_feed` lists what happened on the whole account; check it once an hour,
  not in a loop. `line_item_conversation_read` reads a thread, and `line_item_message_publisher` writes to the
  publisher.

[Statuses and what you do now](/docs/self-serve/statuses)

### 9. Check the live link and pay the publisher

When the publisher sends the live URL, check it and pass or fail it. Then pay the publisher's invoice yourself
and record the payment in Linkio.

- **In the app:** on the **Verification** tab of the row, select **QA PASS** or **QA FAIL (Notify Publisher)**.
  The invoices are at https://www.linkio.com/account/publisher-payments: pay with **Pay Now**, then select
  **Mark as Paid**.
- **With your agent:** `line_item_qa_decision` records your pass or fail. `account_publisher_invoices_list`
  lists the invoices, and `account_publisher_invoice_mark_paid` records a payment after you say you paid. The
  agent moves no money.

[Check the live link and pay the publisher](/docs/self-serve/qa-and-pay)

### 10. Fix problems

A silent or rejecting seller, or a price change: close, reopen or move the placement, or change the price.

- **In the app:** message the seller under **Messages**. A placement that was rejected or went silent shows
  **Replace Site** among its actions.
- **With your agent:** `line_item_close`, `line_item_reopen`, `line_item_replace_site`,
  `line_item_switch_seller` and `line_item_agreed_price_set`, each after your decision.

[When a placement goes wrong](/docs/self-serve/problems)

A refusal you do not understand: [Troubleshooting: refusal codes](/docs/self-serve/troubleshooting).
Words you do not know: [Glossary](/docs/glossary).

## Who you pay

| You pay | For | How |
|---|---|---|
| The publisher (the seller of the site) | The guest post or the link insertion | Directly, by the payment method on the publisher's invoice. Linkio does not move this money. |
| Linkio | Each paid job: site searches past the free sites, articles, checks, and each write call of a key | From money you added or your card. With your own provider keys, the provider bills you for its part at cost. |

The full price list is in [Billing, limits and receipts](/docs/api/billing).

## If your agent sets you up

Copy the address of this page, https://www.linkio.com/docs/self-serve, into Claude Code, ChatGPT or another AI
agent. Tell it: "Set me up on Linkio with this page." The agent does part A or part B below, then part C. It
asks you for the code from Linkio's email, and for your yes before it switches the account or starts anything
that costs money. After part C, you and the agent work through the same steps as above, on the same account.

For the agent: this page as plain text is https://www.linkio.com/docs/self-serve.md. Every docs page has a plain
text copy at the same address with `.md` added. The list of all pages is https://www.linkio.com/llms.txt. No key
and no login is needed to read them.

### A. You do not have a Linkio account yet

1. **Sign up.** The agent sends your email address, a password (8 characters or more), your name and your
   website:

   ```
   curl -s -X POST https://www.linkio.com/api/signup -H 'content-type: application/json' \
     -d '{"email":"you@example.com","password":"<8+ characters>","name":"Your Name","website":"https://example.com"}'
   ```

   The answer is `202` `{"status":"verification_sent"}`.

2. **Ask the person for the code.** Linkio sends the email "Verify Your Email Address - Linkio" to the person's
   mailbox. The agent cannot read that mail: it stops and asks the person for the code that follows the line
   "Did an AI agent create this account for you? Give it this verification code:". The code is good for 24
   hours.

3. **Get the key.** The agent sends the code:

   ```
   curl -s -X POST https://www.linkio.com/api/signup/verify -H 'content-type: application/json' \
     -d '{"token":"<the code>"}'
   ```

   The answer is `201` with these fields:
   - `apiKey`: the account's first key. It starts with `acc_` and is shown only this once: keep it secret.
   - `keyPrefix`: the first characters of the key. The keys page shows the key by this prefix.
   - `accountId`: the account id.
   - `scopes`: what the key may do. That is everything except the spending limits, the card and making keys
     (the Automation level).
   - `expiresAt`: `null`. The key does not expire. The owner can revoke it on the keys page.
   - `next`: the calls that come after. `receipt` reads where the account's money stands (the MCP tool
     `usage_receipt` gives the same), `providerKeys` adds your own OpenAI and DataForSEO keys (the tool
     `provider_key_save`), `pricing` lists the price of each paid job (no key needed), and `addMoney` is the
     page where the person adds money. `receipt` and `providerKeys` are HTTP paths on https://www.linkio.com:
     send the key in `Authorization: Bearer <the key>` or in `X-API-Key`.

   Keep the key safe: hold it in an environment variable, or in a file only the person's user can read
   (`chmod 600`). Never print it, and never paste it into the chat or a log. Send it only in the
   `Authorization` header (or `X-API-Key`).

   The account is on self-serve already. Refusals and limits: [Sign up as an agent](/docs/agents/signup).

4. Go to part C.

### B. You already made an account in the browser

1. **Let the agent in.** Use one of these:
   - Make a key at https://www.linkio.com/account/api-keys. Select the **Automation** level. Give the key to the
     agent.
   - In Claude.ai or ChatGPT, add the Linkio connector and sign in with your Linkio login. No key is needed.
     The steps: [Connect an agent](/docs/agents).

   The agent connects as in part C, step 1.
2. **The agent checks the account first.**
   - `account_me` (no input) returns `account` with `email`, `contactName` and `companyName`. The agent compares
     `email` and `contactName` with the person's. `companyName` counts only when it is set and differs; an empty
     `companyName` is normal. If something differs, the agent asks the person if this is the right account
     before it does anything more.
   - A placeholder name on the right account: the person corrects it at
     https://www.linkio.com/account/settings, or, on the person's yes, the agent sends
     `PUT https://www.linkio.com/api/account/profile` with the key in `X-API-Key` and
     `{"contactName": "...", "companyName": "..."}`. Only the fields sent change. No MCP tool changes them.
   - `account_billing_mode` (no input) returns `mode`, `canSwitchToSelfServe` and `managedCustomer`.
3. **Self-serve.** If `mode` is `self_serve`, go to part C, step 2.
4. **Managed.** If `mode` is `managed`: an account made in the browser starts on the managed plan. The agent does not
   switch it by itself.
   - `canSwitchToSelfServe` is `false` (`managedCustomer` is `true`): the account has a managed plan with Linkio
     (a subscription, or an order paid in the last 60 days). The agent stops and tells the person to contact
     their account manager at Linkio. A switch attempt is refused with `403` `managed_customer`.
   - `canSwitchToSelfServe` is `true`: the agent asks the person. The switch is one way: only Linkio's team moves
     an account back to the managed plan. On the person's yes, the agent calls `account_billing_mode` with
     `{"mode": "self_serve"}`. The person can also switch in the browser: the menu under their name,
     **Your Mode**, **Self-Serve**, then **Switch**. A key made before the switch works on self-serve after it.
     Details: [Start: account, brand and money](/docs/self-serve/start).

### C. Connect and start (both)

1. **Connect.** The agent uses Linkio's MCP server, `https://mcp.linkio.com/mcp`, with the header
   `Authorization: Bearer <the key>`. Claude Code:

   ```
   claude mcp add --transport http linkio https://mcp.linkio.com/mcp --header "Authorization: Bearer acc_your_key"
   ```

   A new tool server shows in the next session. An agent that cannot add one now calls the same tools over HTTP,
   one JSON-RPC request per call:

   ```
   curl -s https://mcp.linkio.com/mcp -H 'Authorization: Bearer acc_your_key' \
     -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
     -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"account_me","arguments":{}}}'
   ```

   The answer is an event stream. The result is the JSON on the `data:` line, and the tool's answer is the text
   in `result.content[0].text`. `"method":"tools/list"` lists every tool (a few hundred; the number depends on the key) with its
   `inputSchema`. For the first job read the `inputSchema` of these five: `client_create`, `website_search`,
   `order_create`, `line_items_add_to_order` and `order_get`. It gives the field names and which fields are
   required. Every tool: [MCP tools](/docs/api/tools). More ways to connect: [Connect an agent](/docs/agents).

2. **Read the account.** `account_me` gives the account id (`account.id`). After a signup by the agent,
   `companyName` is empty: the signup takes no business name. `account_billing_mode` must say `self_serve`
   (part B). `usage_receipt` says whether paid work can start (`canStartPaidWork`) and gives the month's
   spending limit (`budgetCents`, the most Linkio may bill this month) and what is left of it
   (`budgetRemainingCents`). A new account's limit is $50 (`budgetCents: 5000`). The person changes it at
   https://www.linkio.com/billing#limits.

3. **Money.** `canStartPaidWork: false` is normal for a new account. The free steps still work: add a brand,
   search sites (the first 100 sites a day are free), make an order and add sites to it. Paid steps stop
   with a `402` refusal until there is money: a search past the free sites, AI site finding, keyword and topic
   research, articles, and site checks and metrics. To start paid work, the person (not the agent) does one of
   these: adds their own OpenAI and DataForSEO keys at https://www.linkio.com/account/ai-keys (with both keys
   live, a new account also gets a free start), adds money at https://www.linkio.com/shop, or adds a card at
   https://www.linkio.com/billing. Each write call of a key also costs 1c. A daily job charges the writes of
   each finished UTC day, so `usage_receipt` shows them (in `spentCents`) only from the next day. Until then no
   field shows the amount to come. Details: [Who you pay, and for what](/docs/self-serve/money).

4. **The first job.**
   - Add the brand: `client_create` with `name` (the business or brand name, not the person's name), `website`,
     `targetPages` (a list of the page URLs that get links, for example `["https://example.com/services"]`) and
     `description` (what the business does and sells). It returns the brand id. The brand can show
     `clientType: prospect`; that is normal, leave it.
   - Search sites: `website_search` with `clientId` (the brand id), `topicQuery` (the business topic, for
     example "home improvement") or `domain`, and `limit`. Always pass `clientId`: the search then leaves out
     sites the brand already has a link from or has on an order. Use a `limit` of 20 or less: the first 100
     sites a day are free, and every search call counts the sites it returns, a repeated search too. Keep the
     answer instead of searching again. Each site shows its guest post price (`guestPostCost`, in dollars) and
     a `seller` object: `label` (`owner`, `reseller` or `owner_unverified`), `policy` (the seller policy that
     picked it), `proven` (its latest paid placement here cost no more than today's price) and
     `ownerOfferAvailable` (an offer from the owner exists). The seller has no name and no id. Search filters
     such as `maxPrice` are in dollars too. A site with `guestPostCost: null` or `seller.label: null` has no
     listed price or seller yet: skip it. `history.attempts` and `history.lastAttemptAt` count the earlier tries
     on the site, also the ones that did not go live; they are not failures. Failures are in `history.failed`.
   - The agent checks the results before it shows them to the person. It drops the sites that are off the
     business topic, for example news, city or review sites in a search for a niche shop. If few sites fit, it
     searches again with a narrower `topicQuery`, for example "dog beds" instead of "pet supplies".
   - Pick a site, in this order:
     1. The site's topic fits the business. Only sites that fit go on.
     2. Among those, an `owner` seller comes before a `reseller`.
     3. Then a `proven` seller and a high `deliveredCount` (placements that went live on the site) with few
        `history.failed` come before an unproven site.
     4. The `guestPostCost` is within the person's budget: the agent asks the person for the budget when it
        does not know it.

     If every site that fits is an unproven reseller, the agent shows the best 2 or 3 with that caveat and the
     person chooses.
   - Make an order: `order_create` with the brand id (`clientId`). On self-serve an order is only the group your
     placements sit in; it is never paid as a whole. Do not pass `billingType`: the account's mode sets it, so
     the order is self-serve. It returns the order id.
   - Add a site: `line_items_add_to_order`. `orderId` is at the top level, and each site is one entry in
     `items`:

     ```
     {"orderId": "<order id>", "items": [{"clientId": "<brand id>", "assignedDomain": "example.org", "targetPageUrl": "https://example.com/services"}]}
     ```

     Prices on placements are in cents. Each placement's price is the seller's price, which you pay to that
     publisher directly. Leave out `qualify`: it starts a paid analysis of the site (keyword data and a grade)
     and is not needed to add a site.

     The answer gives each added placement's site as `assignedDomain`, and its `estimatedPrice` and
     `wholesalePrice` (in cents). On self-serve
     both are the seller's price (`guestPostCost` × 100). `profitMargin` is only in the order-level
     `orderTotals`, never on a placement, and it is `0` on self-serve.
   - Read it back: `order_get` with `orderId`. Each placement is in `lineItems[]`, with its site as `domain`
     (not `assignedDomain`) and its price at
     `pricing.estimated`, `pricing.wholesale` and `pricing.serviceFee` (in cents; on self-serve `serviceFee` is
     `0`).

   That makes an order with one placement on it. Nothing is sent to a publisher yet. You pay the publisher for
   the placement later, directly, on the publisher's invoice; Linkio charges only its metered fees. Anchor text
   is not needed yet. Set it before the article: `article_gen_anchor_suggestions` gives suggested
   texts, the person picks one, and `article_gen_anchor_apply` applies it by its `suggestionId`. The
   whole walk, with the article, the send and what to watch after:
   [Your first guest post in five minutes](/docs/agents/first-job). The rules the server gives every agent:
   [The rules your agent gets](/docs/agents/rules).
