{"schema_version":"v1","name":"PULL.md","description":"Markdown asset marketplace with x402 payments and receipt-first redownloads","url":"https://pull.md","discovery":{"api_catalog":"https://pull.md/.well-known/api-catalog","service_desc":"https://pull.md/api/openapi.json","service_doc":"https://pull.md/WEBMCP.md","service_meta":"https://pull.md/api/mcp/manifest"},"marketplace":{"enabled_asset_types":["soul","skill"],"ethos":["plain_text_first","portable","diff_friendly","agent_ready","human_readable"]},"auth":{"type":"x402","network":"eip155:8453","currency":"USDC","headers":["PAYMENT-SIGNATURE","PAYMENT-REQUIRED","PAYMENT-RESPONSE","X-CLIENT-MODE","X-WALLET-ADDRESS","X-ASSET-TRANSFER-METHOD"],"deprecated_headers":["PAYMENT","X-PAYMENT"],"client_mode_headers":["X-CLIENT-MODE"],"strict_agent_mode_value":"agent","redownload_headers":["X-WALLET-ADDRESS","X-PURCHASE-RECEIPT","X-REDOWNLOAD-SIGNATURE","X-REDOWNLOAD-TIMESTAMP","X-REDOWNLOAD-SESSION","X-AUTH-SIGNATURE","X-AUTH-TIMESTAMP"],"redownload_modes":{"agent_primary":["X-WALLET-ADDRESS","X-PURCHASE-RECEIPT","X-REDOWNLOAD-SIGNATURE","X-REDOWNLOAD-TIMESTAMP"],"human_session_recovery":["X-WALLET-ADDRESS","X-REDOWNLOAD-SESSION"],"human_signed_recovery":["X-WALLET-ADDRESS","X-AUTH-SIGNATURE","X-AUTH-TIMESTAMP"]},"redownload_session_endpoint":"/api/auth/session","redownload_session_bootstrap_headers":["X-WALLET-ADDRESS","X-AUTH-SIGNATURE","X-AUTH-TIMESTAMP"],"purchase_header_preference":["PAYMENT-SIGNATURE"],"ownership_auth_signature_preferred":"eip4361_siwe_message","ownership_auth_note":"Ownership checks (creator/moderator/session/agent re-download challenge) require SIWE (EIP-4361) message signatures (no token transfer/approval). EOA and EIP-1271 smart-contract wallets are supported.","ownership_auth_timestamp_formats":["unix_ms","iso8601"],"ownership_auth_message_tolerance":["lf","crlf","trailing_newline"],"ownership_auth_timestamp_rule":"Use auth_timestamp = Date.parse(Issued At) from the same auth_message_template. Do not use current wall-clock timestamp.","purchase_receipt_security":"Persist X-PURCHASE-RECEIPT securely per wallet+asset. Treat it as sensitive proof material. Never publish, share, or store in plaintext logs.","common_auth_mistakes":["Using Date.now() instead of Date.parse(Issued At)","Reconstructing SIWE text manually instead of signing exact template","Wallet casing mismatch between signed message and submitted fields"],"agent_key_boundary":"Never send Bankr API keys or signer secrets to PULL.md. PULL.md accepts only signed x402 payment headers."},"facilitator_capabilities":{"runtime_source":"server-configured facilitator URLs","strict_agent_default_transfer_method":"eip3009","note":"Current deployment defaults strict agent purchases to eip3009. permit2 can be requested explicitly but may fail upstream depending on facilitator policy."},"error_codes":{"agent_wallet_hint_required":"Strict agent purchase quote missing X-WALLET-ADDRESS (or wallet_address query).","agent_wallet_hint_required_paid_retry":"Strict agent paid retry missing X-WALLET-ADDRESS (or wallet_address query).","x402_method_mismatch":"Submitted payment method branch does not match wallet-quote transfer method.","invalid_agent_redownload_signature":"Strict agent redownload SIWE signature invalid or timestamp format mismatch.","receipt_required_agent_mode":"Strict agent redownload requires receipt + challenge signature headers."},"wallet_compatibility":{"as_of":"2026-02-14","supported_browser_wallets":["MetaMask","Rabby","Bankr Wallet"],"recommended_for_purchase":"MetaMask or Rabby","bankr_status":"experimental","bankr_note":"Bankr EIP-3009 signatures may fail USDC contract verification in this flow (FiatTokenV2: invalid signature). Prefer EmblemVault until upstream signer compatibility is fixed."},"mcp":{"endpoint":"/mcp","transport":"streamable_http","protocol_version":"2025-06-18","response_streaming":false,"sampling":"not_supported","required_request_headers":{"content-type":"application/json","accept":"application/json, text/event-stream"},"methods":["initialize","notifications/initialized","ping","tools/list","tools/call","prompts/list","prompts/get","resources/list","resources/read"]},"prompts":{"challenge_first_tool":"get_auth_challenge","note":"Use get_auth_challenge to receive SIWE text + timestamp before signing creator/moderator/session/redownload auth requests."},"resources":{"scheme":"pullmd://","examples":["pullmd://docs/manifest","pullmd://docs/webmcp","pullmd://assets","pullmd://assets/<id>"],"legacy_alias_scheme":null},"tools":[{"name":"list_assets","description":"List available markdown assets and pricing","endpoint":"/mcp","method":"POST","rpc_method":"tools/call","rpc_tool_name":"list_assets","arguments_schema":{"type":"object","properties":{"category":{"type":"string","description":"Optional category filter"},"asset_type":{"type":"string","description":"Optional asset type filter (soul, skill)"}},"additionalProperties":false},"returns":{"type":"object","description":"Markdown asset list with metadata and pricing"}},{"name":"get_asset_details","description":"Get full metadata, auth message examples, and purchase endpoint for one markdown asset","endpoint":"/mcp","method":"POST","rpc_method":"tools/call","rpc_tool_name":"get_asset_details","arguments_schema":{"type":"object","properties":{"id":{"type":"string","description":"Asset identifier"}},"required":["id"],"additionalProperties":false},"returns":{"type":"object","description":"Asset details and x402 interaction contract"}},{"name":"check_entitlements","description":"Verify receipt proofs for wallet re-download entitlement (receipt values are sensitive; do not log/share them)","endpoint":"/mcp","method":"POST","rpc_method":"tools/call","rpc_tool_name":"check_entitlements","arguments_schema":{"type":"object","properties":{"wallet_address":{"type":"string"},"proofs":{"type":"array","items":{"type":"object","properties":{"asset_id":{"type":"string"},"receipt":{"type":"string"}},"required":["receipt"],"additionalProperties":false}}},"required":["wallet_address","proofs"],"additionalProperties":false},"returns":{"type":"object","description":"Per-proof entitlement status"}},{"name":"get_auth_challenge","description":"Get a SIWE auth challenge upfront for creator, moderator, session, or redownload flows","endpoint":"/mcp","method":"POST","rpc_method":"tools/call","rpc_tool_name":"get_auth_challenge","arguments_schema":{"type":"object","properties":{"flow":{"type":"string","description":"One of: creator, moderator, session, redownload"},"wallet_address":{"type":"string","description":"Wallet address used to sign the challenge"},"action":{"type":"string","description":"Action name for creator/moderator flows. For flow=creator, defaults to publish_listing."},"asset_id":{"type":"string","description":"Required when flow=redownload"}},"required":["flow","wallet_address"],"additionalProperties":false},"returns":{"type":"object","description":"SIWE challenge template + exact timestamp/signing guidance"}},{"name":"get_listing_template","description":"Get immediate publish payload template for creator markdown asset listings","endpoint":"/mcp","method":"POST","rpc_method":"tools/call","rpc_tool_name":"get_listing_template","arguments_schema":{"type":"object","properties":{},"additionalProperties":false},"returns":{"type":"object","description":"Template payload for immediate creator publish contract"}},{"name":"publish_listing","description":"Creator-auth immediate publish. Returns shareable asset URL and purchase endpoint.","endpoint":"/mcp","method":"POST","rpc_method":"tools/call","rpc_tool_name":"publish_listing","arguments_schema":{"type":"object","properties":{"wallet_address":{"type":"string"},"auth_signature":{"type":"string"},"auth_timestamp":{"type":["number","string"]},"dry_run":{"type":"boolean","description":"Validate listing payload without persisting a new published listing."},"listing":{"type":"object","description":"Creator listing payload. Use get_listing_template for canonical structure.","properties":{"name":{"type":"string","minLength":3,"maxLength":80},"description":{"type":"string","minLength":12,"maxLength":240},"price_usdc":{"type":"number","minimum":0.000001},"content_markdown":{"type":"string","minLength":1,"maxLength":65536}},"required":["name","description","price_usdc","content_markdown"],"additionalProperties":true}},"required":["wallet_address","auth_signature","auth_timestamp","listing"],"additionalProperties":false},"returns":{"type":"object","description":"Published listing summary + share_url + purchase endpoint"}},{"name":"list_my_published_listings","description":"List creator-owned published listings (including hidden listings)","endpoint":"/mcp","method":"POST","rpc_method":"tools/call","rpc_tool_name":"list_my_published_listings","arguments_schema":{"type":"object","properties":{"wallet_address":{"type":"string"},"auth_signature":{"type":"string"},"auth_timestamp":{"type":["number","string"]}},"required":["wallet_address","auth_signature","auth_timestamp"],"additionalProperties":false},"auth_headers":["X-WALLET-ADDRESS","X-AUTH-SIGNATURE","X-AUTH-TIMESTAMP"],"auth_notes":["X-AUTH-TIMESTAMP accepts Unix ms or ISO-8601 (must match SIWE Issued At)"],"returns":{"type":"object","description":"Wallet-scoped list of published listing summaries"}},{"name":"list_published_listings","description":"Public list of currently visible published listings","endpoint":"/mcp","method":"POST","rpc_method":"tools/call","rpc_tool_name":"list_published_listings","arguments_schema":{"type":"object","properties":{},"additionalProperties":false},"returns":{"type":"object","description":"Public listing summaries for discoverability and purchase"}}],"download_contract":{"canonical_base_url":"https://pull.md","endpoint_pattern":"/api/assets/{id}/download","method":"GET","flow_profiles":{"headless_agent":{"purchase":"GET /api/assets/{id}/download with X-CLIENT-MODE: agent -> 402 + PAYMENT-REQUIRED -> retry with PAYMENT-SIGNATURE","redownload":"GET /api/assets/{id}/download with X-CLIENT-MODE: agent + X-WALLET-ADDRESS + X-PURCHASE-RECEIPT + X-REDOWNLOAD-SIGNATURE + X-REDOWNLOAD-TIMESTAMP"},"human_browser":{"purchase":"Connect wallet in UI and submit x402 payment","redownload":"Receipt-first, with optional session bootstrap at /api/auth/session for recovery UX"}},"canonical_purchase_flow":"GET /api/assets/{id}/download is the authoritative x402 flow for payment requirements and paid retry.","first_request":"No payment headers -> returns 402 + PAYMENT-REQUIRED. Include X-WALLET-ADDRESS on this first request for strict wallet binding and deterministic retries.","claim_request":"Include PAYMENT-SIGNATURE with base64-encoded x402 payload to claim entitlement and download","receipt_persistence":"Persist X-PURCHASE-RECEIPT from successful 200 responses in secure storage keyed by wallet+asset. Do not treat receipt values as public.","signing_instructions_field":"402 response bodies include payment_signing_instructions with transfer-method-specific required/forbidden fields and typed-data primary type.","payment_payload_contract":{"top_level_required":["x402Version","scheme","network","accepted","payload"],"eip3009_payload_required":["payload.authorization","payload.signature"],"eip3009_payload_forbidden":["payload.authorization.signature","payload.permit2Authorization","payload.transaction"],"notes":["accepted must exactly equal PAYMENT-REQUIRED.accepts[0]","scheme/network must be top-level (not nested under payload)"]},"redownload_request":"Headless agents should send X-CLIENT-MODE: agent + X-WALLET-ADDRESS + X-PURCHASE-RECEIPT + X-REDOWNLOAD-SIGNATURE + X-REDOWNLOAD-TIMESTAMP. Human/browser flow can use recovery mode.","strict_agent_mode":"When X-CLIENT-MODE=agent is set, re-download requires receipt plus wallet signature challenge headers. Session/auth recovery headers are rejected.","redownload_session_bootstrap":"Bootstrap session at GET /api/auth/session with X-WALLET-ADDRESS + X-AUTH-SIGNATURE + X-AUTH-TIMESTAMP to obtain X-REDOWNLOAD-SESSION.","anti_poisoning_rule":"Always verify the full PAYMENT-REQUIRED.accepts[0].payTo address against the canonical seller address from trusted PULL.md metadata before signing.","redownload_priority":"If wallet+receipt headers are present, entitlement path is processed first (prevents accidental repay even when payment headers are also sent).","note":"auth_message_template may appear in a 402 response as helper text; purchase still requires payment header submission.","domain_note":"Use the canonical production host (pull.md or current deployment host). Preview/alias domains may not reflect the latest contract behavior.","v2_requirement":"Submitted payment JSON must include accepted matching PAYMENT-REQUIRED.accepts[0] exactly.","method_discipline":"Submit exactly one payload method branch. eip3009 => authorization+signature only. permit2 => permit2Authorization(+transaction)+signature only.","transfer_method_selection":"Strict agent mode defaults to eip3009. Optional explicit override: X-ASSET-TRANSFER-METHOD (eip3009|permit2).","facilitator_note":"permit2 may fail upstream depending on facilitator policy. eip3009 is the stable default in this deployment.","duplicate_settlement_protection":"Server applies single-flight settlement idempotency by payer+asset+nonce to reduce duplicate charge attempts from repeated submissions.","wallet_runtime_note":"EmblemVault currently has verified successful purchase + re-download runs. Bankr eip3009 remains experimental.","auth_challenge_recommendation":"For creator/moderator/session/redownload auth, call MCP tool get_auth_challenge first, then sign the exact auth_message_template and set auth_timestamp = Date.parse(Issued At).","permit2_pitfalls":["Set top-level network to accepted.network (eip155:8453), not \"base\".","Use payload.permit2Authorization (not payload.permit2).","Do not include payload.authorization in permit2 mode.","Send permit2 numeric fields as strings.","Set payload.transaction.data to ERC20 approve calldata; do not send empty 0x."]},"contact":{"name":"PULL.md Support","url":"https://pull.md"}}