# Create link

URL: https://docs.hanzo.ai/docs/openapi/link/post-link

> Registers a signed-in AI provider account on a machine.

`POST /v1/link`

> [Link →](https://docs.hanzo.ai/docs/openapi/link) · [All API references →](https://docs.hanzo.ai/docs/openapi) · [Get started →](https://docs.hanzo.ai/docs/guides)

|               |                                        |
| ------------- | -------------------------------------- |
| **Address**   | `https://api.hanzo.ai/v1/link`         |
| **Method**    | `POST`                                 |
| **Operation** | `post_link`                            |
| **Auth**      | `Authorization: Bearer $HANZO_API_KEY` |

Registers a signed-in AI provider account on a machine.

It records that a developer has signed into one provider account on one
machine — a Claude Max or ChatGPT Plus subscription, a Hanzo key, a raw
provider key — and answers 201 with the stored link. Re-reporting the same
(machine, provider, account) UPDATES that link rather than creating a second,
so a collector may call this on every heartbeat. machine and provider are
required (400 otherwise), as is a valid kind, and every field is
length-bounded. Scoped to the caller: a validated principal and a non-empty
org, else 403, so a caller writes only their OWN accounts within their own org.

## Request

8 fields, body `application/json` (required).

| Field      | In   | Type   | Required | Description                                                                                                                                                                                                                                        |
| ---------- | ---- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account`  | body | string | —        | Account is the provider-side account identifier.                                                                                                                                                                                                   |
| `host`     | body | string | —        | Host is the machine's human hostname label.                                                                                                                                                                                                        |
| `kind`     | body | string | —        | Kind decides how the account's inference BILLS and defaults to subscription: a subscription account bills the user's own monthly plan and is metered here for visibility only, while an apikey account bills through commerce on the gateway path. |
| `machine`  | body | string | —        | Machine is the stable machine identifier.                                                                                                                                                                                                          |
| `os`       | body | string | —        | OS is the machine's operating system label.                                                                                                                                                                                                        |
| `plan`     | body | string | —        | Plan is the provider plan label (e.g. "Claude Max").                                                                                                                                                                                               |
| `provider` | body | string | —        | Provider is the AI provider the account belongs to.                                                                                                                                                                                                |
| `usage`    | body | any    | —        | Usage is an optional usage snapshot, clamped and re-serialized to known fields; omitting it keeps the last good one.                                                                                                                               |

## Response

| Status    | Body            | Meaning |
| --------- | --------------- | ------- |
| `201`     | link.linkView   | created |
| `default` | problem-details | refused |

`201` body — 15 fields.

| Field       | In   | Type   | Always | Description                                                                                                                                          |
| ----------- | ---- | ------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account`   | body | string | —      | Account is the provider-side account identifier, when the collector knows it.                                                                        |
| `billing`   | body | string | —      | Billing is how this account's inference bills — plan (the user's own subscription, metered here for visibility only) or commerce (the gateway path). |
| `createdAt` | body | string | —      | CreatedAt is when the link was first registered, RFC 3339 UTC.                                                                                       |
| `host`      | body | string | —      | Host is the machine's human hostname label, from its most recent report.                                                                             |
| `id`        | body | string | —      | ID is the link's opaque handle ("link\_" + 32 hex chars).                                                                                            |
| `kind`      | body | string | —      | Kind is how the account authenticates: subscription or apikey.                                                                                       |
| `lastSeen`  | body | string | —      | LastSeen is when the account last reported, RFC 3339 UTC.                                                                                            |
| `machine`   | body | string | —      | Machine is the stable machine identifier the collector reports.                                                                                      |
| `os`        | body | string | —      | OS is the machine's operating system label.                                                                                                          |
| `plan`      | body | string | —      | Plan is the provider plan label (e.g. "Claude Max").                                                                                                 |
| `provider`  | body | string | —      | Provider is the AI provider this account belongs to (claude, openai, hanzo…).                                                                        |
| `status`    | body | string | —      | Status is linked or revoked.                                                                                                                         |
| `updatedAt` | body | string | —      | UpdatedAt is when the link was last refreshed, RFC 3339 UTC.                                                                                         |
| `usage`     | body | any    | —      | Usage is the last good usage snapshot, clamped and re-serialized to known fields at ingest.                                                          |
| `user`      | body | string | —      | User is the owning subject — the validated caller who registered the link.                                                                           |

Failure carries the platform error shape — see [Errors](https://docs.hanzo.ai/docs/errors).

## Examples

**CLI**

```bash
hanzo auth link create
```

**SDK**

**.ts**

```ts
import { Configuration, LinkApi } from 'hanzoai';

const api = new LinkApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postLink({ account: "<account>", host: "<host>" });
```

**.py**

```python
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import LinkApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = LinkApi(client).post_link(account="<account>", host="<host>")
```

**.go**

```go
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.LinkAPI.PostLink(context.Background()).Execute()
if err != nil {
	return err
}
```

**.rs**

```rust
use hanzo_client::apis::{configuration::Configuration, link_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = link_api::post_link(&cfg, Default::default()).await?;
```

**.java**

```java
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.LinkApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new LinkApi(client).postLink();
```

**HTTP**

```bash
curl -X POST https://api.hanzo.ai/v1/link \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "account": "<account>",
       "host": "<host>"
     }'
```

**MCP**

MCP reaches **link** through the `link` tool, which names its 11 operations with its own verbs — this one among them, under a name only MCP declares. `describe` explains any of them:

```bash
curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "describe",
         "arguments": {
           "op": "list_links"
         }
       }
     }'
```

---

[Link API](https://docs.hanzo.ai/docs/openapi/link) · [All Hanzo APIs](https://docs.hanzo.ai/docs/openapi) · [Interactive reference](https://docs.hanzo.ai/docs/openapi/reference)
