# Platform

> Your platform's settings in each mode, the agent tools of your own that Proof's MCP server offers, and its counts.

Your platform's settings say where Proof sends people and calls: the page where they approve agents, the page where private seals' readers sign in, where your documents are, which origins may frame the editor, and the tools of your own that agents get beside Proof's. Each mode has its own, except the name, which both share and only a live key changes. You can set them here, or all but your tools in the [console](https://developer.proof.exalto.ai/console); a server that sets them on starting keeps them in step with where it runs.

## The platform object

| Attribute | Type | Description |
| --- | --- | --- |
| `id` | string | Your platform's id. |
| `slug` | string | Its short name, in your MCP address. |
| `name` | string | What Proof calls your platform: on consent and seal pages, and to agents. |
| `icon_url` | string or null | Your icon, which MCP clients may show beside your server: Proof's MCP server names it in `serverInfo.icons` when an agent connects. |
| `mode` | string | `test` or `live`, by the key that asked. |
| `embed_origins` | array | The origins that may frame the editor and presence settings. See [Embed origins](/reference/embed/#embed-origins). |
| `consent_url` | string or null | Where Proof sends people to approve an agent, with `?request=areq_…`. See [Agent requests](/reference/api/agent-requests/). Without one, agents can't connect. |
| `reader_url` | string or null | Where Proof sends a private seal's reader to sign in, with `?request=srq_…`. See [Reader requests](/reference/api/seals/#reader-requests). |
| `document_url` | string or null | Where your product shows a document, with `{document}` for its id. Links between documents in the editor, and agents' answers, use it. |
| `mcp_url` | string | Your MCP address in this mode, for your users' agents. |

```json
{
  "id": "plt_6Hq2Lm4R",
  "slug": "acme",
  "name": "Acme Notes",
  "icon_url": "https://acme.com/icon.png",
  "mode": "live",
  "embed_origins": ["https://acme.com"],
  "consent_url": "https://acme.com/proof/connect",
  "reader_url": "https://acme.com/proof/read",
  "document_url": "https://acme.com/docs/{document}",
  "mcp_url": "https://mcp.proof.exalto.ai/acme"
}
```

## Retrieve the platform

`GET /v1/platform`

<Tabs syncKey="lang">
<TabItem label="curl">

```bash
curl https://api.proof.exalto.ai/v1/platform \
  -H "Authorization: Bearer $PROOF_SECRET_KEY"
```

</TabItem>
<TabItem label="Node">

```ts
const platform = await proof.platform.retrieve();
```

</TabItem>
</Tabs>

## Update the platform

`PATCH /v1/platform`

Only the fields you send change. `null` removes a URL.

| Parameter | Type | Description |
| --- | --- | --- |
| `name` | string | Your platform's name, in both modes: with a live key only. |
| `icon_url` | string or null | For this mode: a URL of your icon, for MCP clients to show. |
| `embed_origins` | array | For this mode: origins, such as `https://acme.com`; each is kept as its origin alone. |
| `consent_url` | string or null | For this mode. |
| `reader_url` | string or null | For this mode. |
| `document_url` | string or null | For this mode, with `{document}` where the id goes. |

<Tabs syncKey="lang">
<TabItem label="curl">

```bash
curl https://api.proof.exalto.ai/v1/platform \
  -X PATCH \
  -H "Authorization: Bearer $PROOF_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"consent_url": "https://acme.com/proof/connect", "document_url": "https://acme.com/docs/{document}"}'
```

</TabItem>
<TabItem label="Node">

```ts
const platform = await proof.platform.update({
  consent_url: "https://acme.com/proof/connect",
  document_url: "https://acme.com/docs/{document}",
});
```

</TabItem>
</Tabs>

Returns the [platform](#the-platform-object).

| Error | When |
| --- | --- |
| `403 live_key_required` | `name` sent with a test key. |
| `400 invalid_parameter` | A URL that isn't one, or `embed_origins` that aren't origins. |

## Set your agent tools

`PUT /v1/platform/tools`

Gives your users' agents tools of your own, for what your product keeps itself, such as folders and pins. Proof's MCP server lists them beside its own, and forwards each call to `url`, signed with `secret`. Each call replaces the tools you set before, for this mode. See [Add your own agent tools](/guides/your-own-agent-tools/).

| Parameter | Type | Description |
| --- | --- | --- |
| `url` | string, required | Where Proof posts tool calls. |
| `secret` | string, required | At least 32 characters, which Proof signs each call with. Choose it yourself and keep it. |
| `tools` | array, required | Each `{ name, title?, description, inputSchema }`, as MCP describes a tool. Names are lowercase letters, digits and underscores, and can't be one of Proof's own. |
| `instructions` | string | What agents are told of your tools, after Proof's own instructions. |

<Tabs syncKey="lang">
<TabItem label="curl">

```bash
curl https://api.proof.exalto.ai/v1/platform/tools \
  -X PUT \
  -H "Authorization: Bearer $PROOF_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://acme.com/proof/tools",
    "secret": "'"$ACME_TOOLS_SECRET"'",
    "instructions": "Folders are the person'\''s own: list_folders shows them, move_document files a document in one.",
    "tools": [
      { "name": "list_folders", "description": "The person'\''s folders, in their order.", "inputSchema": { "type": "object", "properties": {} } }
    ]
  }'
```

</TabItem>
<TabItem label="Node">

```ts
await proof.platform.setTools({
  url: "https://acme.com/proof/tools",
  secret: process.env.ACME_TOOLS_SECRET!,
  instructions: "Folders are the person's own: list_folders shows them, move_document files a document in one.",
  tools: [{ name: "list_folders", description: "The person's folders, in their order.", inputSchema: { type: "object", properties: {} } }],
});
```

</TabItem>
</Tabs>

```json
{ "url": "https://acme.com/proof/tools", "tools": ["list_folders"] }
```

| Error | When |
| --- | --- |
| `400 invalid_parameter` on `url` | Not a URL. |
| `400 invalid_parameter` on `secret` | Shorter than 32 characters. |
| `400 invalid_parameter` on `tools` | A tool lacks a name, description or input schema, or its name is one of Proof's. |

## Retrieve counts

`GET /v1/platform/stats`

Counts for your own operations page, in the key's mode: all time, and the last 7 days.

```json
{
  "data": [
    { "label": "Documents", "total": 1204, "week": 87 },
    { "label": "Sealed documents", "total": 312, "week": 19 },
    { "label": "Agents", "total": 96, "week": 8 }
  ]
}
```