{"ok":true,"contract_version":"provider-network/v1","product":"xytara open execution-provider network","summary":"Register an execution endpoint that serves one or more capabilities; once an operator activates it, the runtime routes PAID (x402-settled) agent calls to your /execute, surfaces your output as the buyer's deliverable, and accrues your revenue-share for payout.","lifecycle":["1. REGISTER your provider (endpoint_url + the capabilities you serve + your revenue_share_bps + payout_address). You receive an owner_secret (save it — shown once).","2. Your provider lands status:'pending' and is NOT routable yet.","3. An OPERATOR activates it (status:'active'). Activation requires a payout_address on the record.","4. When a buyer pays (x402) for a capability you serve, the runtime POSTs the job to your endpoint_url; you execute and return the deliverable (a 2xx WITH result.output / output_payload / output — an empty 2xx is not a delivery and is not charged).","5. On your success the payment settles on-chain and your revenue_share accrues exactly, in USDC base units ($0.000001), so even a $0.001 price earns its full share.","6. A payout sweep pays your available balance to your payout_address once it reaches 100 cents (POST /v1/provider-network/payouts/sweep, run on the operator's schedule); the operator can also pay out any time. Track it yourself via GET /providers/<id>/earnings with your owner_secret; rotate the secret with POST /providers/<id>/rotate-secret."],"registration":{"endpoint":"POST /v1/provider-network/register","auth":{"modes":["operator-bearer: send Authorization: Bearer <registration token> (obtain from the operator)","open (permissionless): no bearer required, but rate-limited and pending-capped"],"open_registration_enabled":true,"note":"A re-registration of an EXISTING provider_id ALWAYS requires its owner_secret, in either mode."},"body":{"provider_id":"string, optional — stable id; omit to be assigned a random one. Keep it: it is your identity.","owner_secret":"string, REQUIRED only when updating an existing provider_id (returned once at first registration).","label":"string, optional display name.","endpoint_url":"string, REQUIRED — your https /execute URL the runtime will POST jobs to.","task_refs":"string[] — task refs you serve (e.g. 'adapter.mcp.invoke'). At least one selector across task_refs/tool_names/integration_ids is required.","tool_names":"string[] — specific tool names you serve (matched against the call's body.tool_name).","integration_ids":"string[] — integration-family ids you serve.","revenue_share_bps":"integer 0..8000 — your share of each settled amount in basis points (e.g. 7000 = 70%). Current operator cap: 8000.","offers":"array, optional — YOUR price per capability: [{ tool_name | task_ref (one of them, and one you declared above), title (1-80 chars), description? (<=300), price_usd (0.001..100.00 in steps of 0.001, e.g. \"0.002\") }], at most 50. A call that routes to you for an offered capability is quoted and debited (credits) at YOUR price, and your revenue_share applies to it; a single x402 payment is challenged at no less than the per-payment minimum ($0.005, it covers the facilitator's per-settlement fee) while your share is still computed on your own price; without an offer the platform's catalog price applies. Offers are metadata: changing a price never reverts an active provider to pending. Omit the field on an update to keep the existing offers; send [] to clear them.","payout_address":"string — where your revenue-share is paid (eip155 address shape-checked for eip155 networks). Optional at registration, REQUIRED for activation.","payout_network":"string, optional — default 'eip155:8453' (Base).","payout_asset":"string, optional — default 'USDC'.","auth_token":"string, optional — a bearer the runtime presents to YOUR /execute (so you can authenticate it).","ens_name":"string, optional — an ENS name you own (x402 payee-name, wg-identity#36), e.g. 'myservice.eth'. Lowercase ASCII .eth names only (a-z, 0-9, hyphen). On the name, set the text record org.x402.origins to include your endpoint_url's origin, and set the address record for your payout_network (Base: coin type 2147492101; or the default EVM address, coin type 2147483648) to your payout_address, or list it as CAIP-10 in the text record org.x402.payto. Checked against Ethereum mainnet at registration and daily; the verdict is on your record (name_binding), and while it is payee-bound your delivery receipts name you by it. Not routing-material: setting or changing it never reverts an active provider to pending. Omit on an update to keep it; send null to clear it."},"response":{"ok":true,"provider_id":"<your id>","status":"pending","owner_secret":"prvown_… (RETURNED ONLY ON FIRST REGISTRATION — store it securely; required for every future update)","provider":"{ public view: no auth_token, no owner_secret }"}},"execution_contract":{"description":"When a paid call for a capability you serve is routed to you, the runtime sends an HTTP POST to your endpoint_url. Execute the work and return the deliverable.","request":{"method":"POST","headers":{"content-type":"application/json","authorization":"Bearer <your auth_token> (only if you registered one)"},"body":{"command":"string — the command label","task_ref":"string — the task ref being invoked","tasks":"array — the task set (when multi-task)","body":"object — the buyer's input, e.g. { tool_name, arguments }","account_id":"string — the buyer's account ref","quote":"object — the priced quote for this call","authorization_context":"object — SANITIZED payment context: { ok, verification_mode, wallet_id, age_seconds, payment_payload (scalar facts only) }. Never the buyer's signed authorization, signatures, or settlement material."}},"endpoint_policy":"endpoint_url must be https and publicly routable on the hosted network (loopback, private, link-local and metadata hosts are refused, re-checked by DNS at dispatch); URLs with embedded credentials are refused; redirects are never followed.","execution_budget":"One buyer call has a total wall-clock budget (default 50s, inside the x402 authorization window) shared across ride-out retries and failover; your timeout_ms is capped at 30000 ms. Finish well inside it — a call that outlives the authorization cannot settle.","response":{"on_success":"Return HTTP 2xx with the deliverable. The runtime surfaces your output from result.output OR a top-level output_payload / output. A 2xx with none of these (empty or non-JSON body, null output) is treated as NOT delivered: the buyer is not charged, nothing accrues, and the call is not retried elsewhere (your side did answer).","example_success_bodies":["{ \"result\": { \"output\": { \"...\": \"your real result\" } } }","{ \"output_payload\": { \"...\": \"your real result\" } }"],"on_failure":"Return a non-2xx status.","failure_semantics":{"failover_safe_statuses":[408,429,503],"note":"408/429/503 (and connection-refused/DNS) are treated as 'did NOT process' — the runtime may RETRY you and/or FAIL OVER to another provider. Any OTHER failure (5xx, timeout, connection reset, malformed) is treated as AMBIGUOUS: the runtime will NOT retry/fail-over (your side may have executed). Design /execute to be idempotent per request so a safe retry is harmless."},"timeout_ms_default":10000}},"routing":{"capability_matching":"A call routes to you if its task_ref is in your task_refs, OR its body.tool_name is in your tool_names, OR an integration id matches your integration_ids. Only ACTIVE providers are routable. The most specific match is preferred: a tool_names match outranks a task_refs match, which outranks an integration_ids match; reputation orders providers of equal specificity.","health":{"description":"Consecutive failures mark you unhealthy and temporarily exclude you from routing; a cooldown then lets you back (half-open) for one retry; a success resets you.","unhealthy_threshold":3,"unhealthy_cooldown_ms":60000},"reputation":{"description":"The runtime tracks your lifetime success rate and prefers higher-reputation providers within the healthy tier. New providers get an optimistic score (a fair first shot); one early failure is recoverable (not disqualifying). The operator may enable recency decay so recent performance outweighs stale history (your raw lifetime counts are still shown either way).","routing_score":"(success + 2) / (success + failure + 2)","recency_decay":0.95},"failover_max_candidates":3,"note":"Operator-pinned execution targets (if any) take precedence over the registry for a given capability.","declared_tools":"If you declare tool_names, you serve exactly those tools: your task_refs place you on a lane but do not claim other tools on it. A call that names a tool on a lane the operator's own provider serves goes to you only if you declared that tool. A call priced by your offer is routed to you first.","calls":"A call routed to you carries exactly one task (multi-task calls are refused). Built-in integration ids (builtin.*) never route calls to you; provider ids of the operator's own providers are reserved."},"economics":{"pricing":"Your offers (registration.body.offers) set the per-call price of the capabilities you serve: the buyer's 402 challenge advertises that amount in USDC on every configured network, the payment is verified against it, a credits_first call is debited its credits equivalent (price / credit value, rounded up), and GET /v1/catalog lists every active provider's offers under provider_offers. Capabilities without an offer are priced by the platform catalog.","mcp_distribution":"An offer with a tool_name is also listed by the naxytra MCP server (https://mcp.naxytra.com/mcp, tools/list) under that name, after the server's own tools (a name colliding with a built-in tool is skipped), and a tools/call for it is proxied to this runtime — so MCP clients discover and pay for your tool without any integration on your side.","settlement":"Buyers pay via x402 (gasless USDC on Base mainnet) or prepaid credits. The runtime settles on-chain only AFTER your execution succeeds — a failed call does not charge the buyer. Calls you run are never payable with testnet USDC, nor on the fixed-price L402 / BOLT lanes (they are not bound to your price).","revenue_share":"Your exact share is settled_amount * revenue_share_bps / 10000 per call, accrued in USDC base units (ledger rows show gross_atomic / provider_share_atomic next to the cents fields), so a $0.001 call at 80% earns exactly $0.0008. settled_amount = min(your price, the amount actually settled for the call) — never money that was not collected, and never more than your own price; each ledger row records its settlement_basis. Payouts move whole cents; the sub-cent part of your balance stays until it reaches a cent.","delivery_receipts":"Every paid call routed to you returns the buyer a signed delivery receipt (naxytra-delivery-receipt/1) naming your provider_id (and, while your ENS name is payee-bound, delivery.provider_name with that name and when it was checked) and the sha256 of the request and of the output you returned, bound to the payment (for x402, the settlement tx). Keys: GET /.well-known/delivery-receipt-keys. It attests what you delivered — never whether it was correct.","payouts":"Your accrued share is paid to your payout_address in USDC on Base through a payout sweep once your available balance reaches 100 cents (the operator runs the sweep on a schedule and can pay out any time; reconciled ledger: create -> on-chain send -> confirm, idempotent, double-pay-safe). Amounts are tracked in the quote's minor unit (USD_CENTS). Ledger rows and payouts are scoped to your registration: a removed-and-re-registered provider_id starts a fresh ledger and never inherits another owner's rows.","payout_sweep_min_minor":100},"discovery":{"list":"GET /v1/provider-network/providers — public; lists ACTIVE (vetted) providers with capabilities, status, health, and reputation (never secrets). Pending/suspended records are visible to the operator only.","self":"GET /v1/provider-network/providers/<provider_id> — your public record.","earnings":"GET /v1/provider-network/providers/<provider_id>/earnings — your OWN earnings (read-only): payout_state (accrued/paid/pending/available/owed), your settlement rows, and your payout history. Authenticate with YOUR owner_secret via the 'x-provider-owner-secret' header (or Authorization: Bearer <owner_secret>) — this is the provider side, it needs no operator bearer.","rotate_secret":"POST /v1/provider-network/providers/<provider_id>/rotate-secret — authenticate with your CURRENT owner_secret (same header or Bearer); the new secret is returned once and the old one stops working immediately.","name_check":"POST /v1/provider-network/providers/<provider_id>/name-check (owner_secret, or the operator) — re-runs the ENS name check now (at most once a minute) after you change the name's records. Verdicts follow the payee-name spec: true / payee-bound; false / origin-not-listed, payto-not-listed, name-expired, name-not-normalized; inconclusive / resolution-failed, name-in-grace, no-records, unsupported-name. A failed chain read is always inconclusive, never false. Records served off-chain (CCIP-Read) are not followed yet and read as inconclusive.","self_test":"POST /v1/provider-network/providers/<provider_id>/self-test (owner_secret, or the operator) — the runtime POSTs a synthetic unpaid job { command: \"provider.self_test\", body: { self_test: true, tool_name, arguments: {} }, quote: { amount_minor: 0, self_test: true } } to your endpoint exactly like a paid job (same policy, same bearer) and records whether you answered the contract (a 2xx with result.output / output_payload / output). Run it before asking for activation; the outcome is on your public record (last_self_test) and in the operator's daily report. A reference /execute implementation that passes it: https://www.naxytra.com/providers/execute-reference.mjs (guide: https://www.naxytra.com/providers/quickstart)."},"operator_gated":["activation: POST /v1/provider-network/providers/:id/status { status } (requires a payout_address on the record)","payouts: POST /v1/provider-network/providers/:id/payouts (+ /payouts/:id/confirm|cancel, /payouts/execute), POST /v1/provider-network/payouts/sweep ({ dry_run: true } previews the payable set and the signer state)","removal: POST /v1/provider-network/providers/:id/remove"],"guidance":["Be idempotent per request — key on quote.quote_id (unique per buyer call): retries and failover can re-send a provably-not-processed job, and some proxies return 503 after forwarding a request.","Be reliable — health and reputation gate your routing and ordering.","Return a 429 with Retry-After when overloaded (it is treated as 'did not process' and is safely retried)."]}