# Zinin M2M Hub — connection guide 121 pay-per-call tools, 12 MCP bundles, at https://api.timzinin.com. Paid with x402 (USDC on base), no accounts and no API keys. Privacy policy: https://api.timzinin.com/privacy ## What this is 121 paid tools in 12 MCP bundles, at https://api.timzinin.com. Each tool is a hosted automation: you POST its input, it runs, you get its output. Every call is priced individually and paid per call. - Payment protocol: x402. The server speaks v2 and keeps v1 working for existing clients; the header you send decides which one answers you. - Money: USDC on base (CAIP-2 `eip155:8453`, asset `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`). - Scheme: `exact`. - Pay to: `0x409D32aD39C02BC9B23a8b2d447532ed801b12dE`. - No account, no API key, no rate-limit token. The payment is the authentication. ## Free endpoints — no payment, no wallet - `GET /` — HTML catalog of every tool and bundle. - `GET /health` — status, number of active tools, network, facilitator. - `GET /.well-known/x402` — x402 v2 discovery manifest: one entry per paid resource plus the list of MCP bundles. - `GET /openapi.json` — full OpenAPI document with one concrete path per tool, its input schema and its price under `x-payment-info`. - `GET /api/{slug}/schema` — the input JSON Schema of one tool. - `GET /docs`, `GET /llms.txt`, `GET /privacy` — this document (HTML and plain text) and the privacy policy. - On MCP: `initialize`, `ping`, `tools/list` and the `pricing_info` tool in every bundle are free. `pricing_info` is the wallet-less way in: call it on any bundle to get every tool's price, the payTo address, the network and the scheme before you sign anything. ## REST: how a paid call works `POST https://api.timzinin.com/api/{slug}` with the tool input as the JSON body. - Send no payment header and you get HTTP 402. The v1 requirements are in the JSON body (`x402Version`, `accepts[]`, `error`); the v2 requirements are base64-encoded in the `PAYMENT-REQUIRED` response header, normally along with the tool's input schema and examples (that extra declaration is trimmed when a schema is too large for the header budget — the payment requirements themselves are always there). - Pay with x402 v2: header `PAYMENT-SIGNATURE: `. - Pay with x402 v1 (legacy, still supported): header `X-PAYMENT: `. - Whichever of the two headers you send fixes the protocol version of the whole response, including the name of the receipt header. - Success is HTTP 200 with `{"results": [...], "meta": {"run_ms", "item_count", "settled", "transaction"}}`, plus the base64 settlement receipt in `PAYMENT-RESPONSE` (v2) or `X-PAYMENT-RESPONSE` (v1). - Output is released only after settlement is confirmed. If the run succeeded but settlement did not confirm, you get 402 and no data — retry the same payment and the server settles the run it already has instead of running it again. # 1. see what a call costs (no wallet needed) curl -i -X POST https://api.timzinin.com/api/afad-earthquake-operations-router \ -H 'content-type: application/json' -d '{}' # -> HTTP/1.1 402, PAYMENT-REQUIRED: # 2. pay and run curl -i -X POST https://api.timzinin.com/api/afad-earthquake-operations-router \ -H 'content-type: application/json' \ -H 'PAYMENT-SIGNATURE: ' \ -d '{ ...tool input... }' Status codes: 400 malformed v2 payment payload, unparsable body, schema violation or oversized body; 402 payment required, invalid, or settlement not confirmed; 404 unknown tool; 409 this payment payload was already used (sign a fresh one); 429 rate limited; 502 tool run failed or facilitator unreachable; 504 tool run timed out; 500 internal error. ## MCP: how a paid call works `POST https://api.timzinin.com/mcp/{bundle}` — JSON-RPC 2.0 over streamable HTTP. One JSON response per request, no SSE stream. Methods: `initialize`, `notifications/initialized`, `ping`, `tools/list`, `tools/call`. - Payment is not an HTTP header here. It goes inside the request parameters: `params._meta["x402/payment"]` holds the payment payload as a plain JSON object — the same object you would base64-encode for REST, not base64 here. - Every payment outcome of a `tools/call` arrives inside a JSON-RPC envelope with HTTP 200 — "you have to pay", "payment invalid", "already used", a failed run: all of them `result.isError = true`, with the PaymentRequired object in `structuredContent` and the identical JSON in `content[0].text` for the payment ones. Transport-level refusals are ordinary HTTP statuses instead, with a plain `{"error": ...}` body and no envelope at all: 429 over the rate limit, 403 wrong `Origin`, 404 unknown bundle, 400 oversized body, 500 payment misconfigured on our side. The one mixed case is an unsupported protocol version — HTTP 400 carrying a JSON-RPC error object. So: check the status before parsing the body as JSON-RPC. - On success the tool output is JSON in `content[0].text`, and the settlement receipt is `result._meta["x402/payment-response"]` (`success`, `transaction`, `network`, `payer`). - A JSON-RPC notification (a request with no `id` member) is never executed and never answered: HTTP 202, empty body. Always send an `id` for a paid call. - The protocol version is checked wherever you put it: the `MCP-Protocol-Version` header, `params._meta["io.modelcontextprotocol/protocolVersion"]`, and `params.protocolVersion` on `initialize`. Supported: `2024-11-05`, `2025-03-26`, `2025-06-18`, `2025-11-25`. An unsupported value in any of those places — or a header and a body that disagree with each other — is rejected with HTTP 400 and JSON-RPC error -32000. - If your client sends an `Origin` header it must match `https://api.timzinin.com`, otherwise the request is refused with HTTP 403 (browser DNS-rebinding guard). Command-line and server-side clients normally send no Origin and are unaffected. POST https://api.timzinin.com/mcp/apify-market-intelligence { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "afad-earthquake-operations-router", "arguments": { ...tool input... }, "_meta": { "x402/payment": { ...signed x402 payload... } } } } ## Rate limits - Paid attempts: 30 per minute per IP address, fixed window. - Unpaid requests (pricing probes, discovery crawls, free MCP methods): 242 per minute per IP address. That window is computed from the size of the catalog, so a full crawl of every listed resource is never throttled by it. - The two buckets are independent, and both are shared between REST and MCP: a burst of one kind never starves the other, and switching transport mid-burst does not reset anything. - Every request to an MCP bundle endpoint draws from the unpaid bucket; a `tools/call` that actually runs a tool additionally draws from the paid bucket. - Over the limit is HTTP 429. ## Input limits - Request body cap: 32768 bytes — the raw REST body and the whole MCP JSON-RPC envelope alike. - Unknown top-level input fields are rejected rather than ignored, so a typo fails loudly instead of silently changing what you paid for. - URL-shaped input fields must point at public http/https addresses; private, loopback and link-local targets are refused. - Each tool carries its own run timeout and its own cap on how many items one run may return. Neither number is published as such: what you can read is `maxTimeoutSeconds` in the 402 requirements, which is the validity window we ask your payment to cover — the tool's run timeout plus 30 seconds for verify and settle, so it is an upper bound on the run rather than the run timeout itself. The item cap is applied server-side and is not published anywhere; ask us if it matters for what you are building. ## Everything else - Machine-readable catalog: `/openapi.json` and `/.well-known/x402`. - Liveness: `/health`. - What we store and who else sees it: `/privacy`. - This page as plain text for agents: `/llms.txt`. - Questions: tim.zinin@gmail.com