> For the complete documentation index, see [llms.txt](https://archer-bot.gitbook.io/archer.bot/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://archer-bot.gitbook.io/archer.bot/for-builders/partner-dispatch-contracts.md).

# Partner REST dispatch contracts

> Companion to [Publishing a Partner Intent](/archer.bot/for-builders/publishing-a-partner-intent.md). That guide covers onboarding; this page is the **wire contract** Bob implements on `POST` (not GET).

> ## Verifying Archer's signature is mandatory
>
> **You cannot go live until your endpoint verifies the `archerSignature` on every dispatch.** At activation, Archer sends your endpoint a deliberately **unsigned / forged** request. If your endpoint accepts it (does not return `401`/`403`), Archer will **not** activate your intent.
>
> **Why this is required:** your `toolEndpoint` is a public URL — anyone who discovers it can POST to it. A signed request is the only way to know a call genuinely came from Archer. Without verification, anyone could call your endpoint directly, run up your provider costs, and bypass the per-call payment and attribution model entirely. The signature is **asymmetric**: you verify with Archer's published public key (`/.well-known/archer-public-key`) and never hold any secret that could impersonate Archer. Verification details — canonical JSON, the public-key endpoint, and a copy-paste verifier — are in [Publishing a Partner Intent → Verify the signature](/archer.bot/for-builders/publishing-a-partner-intent.md#step-3-verify-the-signature).

## REST is always `POST`

Archer never calls Bob with GET query strings. Every dispatch is:

```
POST <your toolEndpoint>
Content-Type: application/json
Idempotency-Key: <requestId>
```

The body is the signed [request envelope](/archer.bot/for-builders/publishing-a-partner-intent.md#step-2-the-request-envelope). Bob verifies `archerSignature`, reads `args`, runs logic, returns the [response envelope](/archer.bot/for-builders/publishing-a-partner-intent.md#step-4-the-response-envelope).

## What is in `args`?

`args` is a **JSON object**. Its shape depends on **which Archer consumer path** invoked the intent — not on HTTP verb.

| Path                                                                | When                                                                                 | What Archer sends in `args`                                                                                                                              |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **AgentLoop** (`@handle` in chat, non-flat-fee or LLM-routed)       | Alice's message is classified; the LLM calls your tool using your `parametersSchema` | Structured fields your schema declares (e.g. `{ "ticker": "ETH" }`). Validated against `parametersSchema` before dispatch.                               |
| **Flat-fee gate** (`feeRateUnit` = `flat_stablecoin` / `flat_usdc`) | Pay-first partner (e.g. `@DemoAnalyst` on test)                                      | **Opaque** `{ "query": "<user text minus @handle>" }` only. Archer does **not** parse tickers, timeframes, or portfolio fields. Bob owns NL → Bob's API. |

Both paths use the **same** signed envelope and `POST`. The difference is who produces `args` (LLM vs opaque pass-through).

### Example — AgentLoop (structured)

Alice: `@TokenAnalyzer what's the price of ETH?`

```json
{
  "requestId": "…",
  "intentDefinitionId": "…",
  "userId": "…",
  "args": { "ticker": "ETH" },
  "timestamp": 1715712345678,
  "archerSignature": "…"
}
```

### Example — Flat-fee (opaque)

Alice: `@DemoAnalyst chart ETH over the last 30 days`

After EIP-3009 payment, Archer dispatches:

```json
{
  "args": { "query": "chart ETH over the last 30 days" }
}
```

Bob's server parses the opaque `query` into its own schema — Archer never inspects it.

## Flat-fee payment rail

Flat-fee intents add a **pay-before-dispatch** step on Archer's side:

1. Alice sees a quote (USDC on Base Sepolia, gross amount, partner + Archer split).
2. Alice signs **EIP-3009** `ReceiveWithAuthorization` into `ArcherFlatFeePayer`.
3. Archer submits on-chain, then **POSTs** the opaque `{ query }` envelope to Bob's REST endpoint.

Bob's REST handler is unchanged — same signature verification, same response shape. Payment is between Alice and Archer's contracts; Bob is paid via the attestation split configured on the `IntentDefinition` row.

**Test public key:** `https://archer-api-test.up.railway.app/.well-known/archer-public-key`

## Can Bob receive Alice's portfolio (or other context)?

**Today (v1):** No first-party enrichment. Archer forwards:

* `userId` (opaque pseudonymous id in the envelope)
* `args` (structured or `{ query }` only)
* `requestId` for idempotency

Archer does **not** attach wallet balances, holdings, or thread history to partner REST calls unless those appear inside `query` text or in LLM-produced `args` fields your schema asks for.

**Not read-only:** REST dispatch is not limited to "GET-style" reads. Bob can execute writes, call paid APIs, or return rich JSON + `archerEmbed` charts. The constraint is **what Archer puts in `args`**, not HTTP semantics.

**Future:** Optional **context payloads** Alice opts into (e.g. portfolio snapshot, risk profile) as extra envelope fields or structured `args` keys — with explicit consent, redaction, and Bob disclosure in the marketplace UI. Requires:

* Schema/versioning for `inputContract` / context attachments
* Privacy review (what leaves Archer's boundary)
* Bob opt-in per intent

Until that ships, if Bob needs portfolio-aware analysis, Alice must describe holdings in natural language (opaque `query`) or you declare explicit optional fields in `parametersSchema` for the AgentLoop path.

## MCP\_HTTP binding

Same `args` semantics. Archer connects as an MCP client and `callTool(publicIdentifier, args)`. Signature material is forwarded on HTTP headers (`X-Archer-Signature`, etc.). See [Publishing a Partner Intent — MCP\_HTTP](/archer.bot/for-builders/publishing-a-partner-intent.md#mcp_http-recommended-if-you-already-run-an-mcp-server).

## Reference implementations

| Artifact                            | Location                                                                                                                  |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Bob verifier (Node + Python)        | [`archer-partner-examples`](https://github.com/Archer-Laboratories/archer-partner-examples)                               |
| MCP\_HTTP header verification notes | [`mcp-verifier-notes.md`](https://github.com/Archer-Laboratories/archer-partner-examples/blob/main/mcp-verifier-notes.md) |

## Roadmap

* Public developer docs (this page)
* Published verifier libraries (npm / PyPI)
* Flat-fee on-chain payment rail
* Structured input / context contracts (future)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://archer-bot.gitbook.io/archer.bot/for-builders/partner-dispatch-contracts.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
