{"agentsJson":"0.1.0","info":{"title":"bitSimp API","version":"1.0.0","description":"Agent-callable flows for bitSimp, a Bitcoin-only anonymous peer-to-peer content marketplace. Creators post content behind a price wall denominated in satoshis; buyers pay via the Lightning Network.\n\nFlow actions reference operations in the bitSimp OpenAPI 3.1 document at https://bitsimp.com/openapi.json.\n\n# Authentication\n\nbitSimp is passwordless. Authentication proves ownership of a secp256k1 key pair via LNURL-auth (Lightning, ECDSA) or NIP-07 (Nostr, BIP-340 Schnorr). Headless clients (scripts, LLM agents) should use the single-call flows `authenticate_lnurl` and `authenticate_nostr`, which return an HttpOnly session cookie; include that cookie in all subsequent requests.\n\n# Payments\n\nAll monetary amounts are integer satoshis. Purchases, tips, deposits and withdrawals are Lightning-Network operations; never spend a user's sats without explicit human approval."},"sources":[{"id":"bitsimp_api","path":"https://bitsimp.com/openapi.json","description":"bitSimp public HTTP API (OpenAPI 3.1) — LNURL-auth & NIP-07 auth, posts, comments and balance."}],"flows":[{"id":"authenticate_lnurl","title":"LNURL-auth login (headless / LLM agents)","description":"Authenticate a client by proving ownership of a secp256k1 Lightning key pair. Invoke this flow twice, because the signature must be computed over the fresh challenge and no API action can sign on the client's behalf: 1) Invoke with only `pubkey` — the executor runs the challenge operation and returns a fresh 64-char hex k1. 2) Sign the raw 32-byte challenge with ECDSA (DER-encoded, as hex). 3) Invoke again with `pubkey`, `challenge` (the k1 from step 1) and `sig` — the executor runs the login operation, which on success sets an HttpOnly session cookie that must be sent with every subsequent request.","actions":[{"id":"get_challenge","sourceId":"bitsimp_api","operationId":"lnurlAuthChallenge"},{"id":"log_in","sourceId":"bitsimp_api","operationId":"lnurlAuthLogin"}],"links":[{"origin":{"actionId":"get_challenge","fieldPath":"responses.success.challenge"},"target":{"actionId":"log_in","fieldPath":"requestBody.challenge"}}],"fields":{"parameters":[{"name":"pubkey","description":"33-byte compressed secp256k1 public key as 66-char hex.","required":true,"type":"string"},{"name":"sig","description":"DER-encoded ECDSA signature over the raw 32-byte challenge, as hex. Omit on the first invocation (challenge issuance); required on the second.","required":false,"type":"string"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"pubkey":{"type":"string"},"challenge":{"type":"string","minLength":64,"maxLength":64},"sig":{"type":"string"}},"required":["pubkey"]}}},"required":true},"responses":{"success":{"type":"object","properties":{"success":{"type":"boolean","const":true},"id":{"type":"string","format":"uuid"}},"required":["success","id"]}}}},{"id":"authenticate_nostr","title":"NIP-07 Nostr login (headless / LLM agents)","description":"Authenticate a client by proving ownership of a Nostr key. Invoke this flow twice, because the signed event must embed the fresh challenge and no API action can sign on the client's behalf: 1) Invoke with only `pubkey` — the executor runs the challenge operation and returns a fresh 64-char hex challenge. 2) Embed the challenge in the `content` (or a `[\"challenge\", …]` tag) of a Nostr event and sign it (BIP-340 Schnorr, 32-byte x-only public key). 3) Invoke again with `pubkey`, `challenge` (from step 1) and the signed `event` — the executor runs the login operation, which on success sets an HttpOnly session cookie that must be sent with every subsequent request. The event `pubkey` must match the submitted `pubkey`.","actions":[{"id":"get_challenge","sourceId":"bitsimp_api","operationId":"nostrNip07Challenge"},{"id":"log_in","sourceId":"bitsimp_api","operationId":"nostrNip07Login"}],"links":[{"origin":{"actionId":"get_challenge","fieldPath":"responses.success.challenge"},"target":{"actionId":"log_in","fieldPath":"requestBody.challenge"}}],"fields":{"parameters":[{"name":"pubkey","description":"32-byte x-only public key as 64-char hex.","required":true,"type":"string"},{"name":"event","description":"Signed Nostr event (NIP-01) embedding the challenge. Omit on the first invocation (challenge issuance); required on the second.","required":false,"type":"object"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"pubkey":{"type":"string"},"challenge":{"type":"string","minLength":64,"maxLength":64},"event":{"type":"object"}},"required":["pubkey"]}}},"required":true},"responses":{"success":{"type":"object","properties":{"success":{"type":"boolean","const":true},"id":{"type":"string","format":"uuid"}},"required":["success","id"]}}}},{"id":"browse_feed","title":"List posts from the feed","description":"Fetch the cursor-paginated marketplace feed, optionally filtered by creator alias, price range, file type, or purchase/unlock state. Archived posts are hidden from everyone except their owner. Anonymous browsing is supported.","actions":[{"id":"list_posts","sourceId":"bitsimp_api","operationId":"listPosts"}],"links":[{"origin":{"actionId":"browse_feed","fieldPath":"parameters.author"},"target":{"actionId":"list_posts","fieldPath":"parameters.author"}},{"origin":{"actionId":"browse_feed","fieldPath":"parameters.price_min"},"target":{"actionId":"list_posts","fieldPath":"parameters.price_min"}},{"origin":{"actionId":"browse_feed","fieldPath":"parameters.price_max"},"target":{"actionId":"list_posts","fieldPath":"parameters.price_max"}},{"origin":{"actionId":"browse_feed","fieldPath":"parameters.includes_file_type"},"target":{"actionId":"list_posts","fieldPath":"parameters.includes_file_type"}},{"origin":{"actionId":"browse_feed","fieldPath":"parameters.purchased"},"target":{"actionId":"list_posts","fieldPath":"parameters.purchased"}},{"origin":{"actionId":"browse_feed","fieldPath":"parameters.unlocked"},"target":{"actionId":"list_posts","fieldPath":"parameters.unlocked"}},{"origin":{"actionId":"browse_feed","fieldPath":"parameters.locked"},"target":{"actionId":"list_posts","fieldPath":"parameters.locked"}},{"origin":{"actionId":"browse_feed","fieldPath":"parameters.cursor"},"target":{"actionId":"list_posts","fieldPath":"parameters.cursor"}},{"origin":{"actionId":"browse_feed","fieldPath":"parameters.page_size"},"target":{"actionId":"list_posts","fieldPath":"parameters.page_size"}}],"fields":{"parameters":[{"name":"author","description":"Filter by creator alias.","required":false,"type":"string"},{"name":"price_min","description":"Minimum price in satoshis.","required":false,"type":"string"},{"name":"price_max","description":"Maximum price in satoshis (0 = only free posts).","required":false,"type":"string"},{"name":"includes_file_type","description":"Comma-separated buckets: images, videos, audio, other.","required":false,"type":"string"},{"name":"purchased","description":"Only posts purchased by the authenticated user.","required":false,"type":"string"},{"name":"unlocked","description":"Only posts already unlocked (free or purchased).","required":false,"type":"string"},{"name":"locked","description":"Only locked/paywalled posts.","required":false,"type":"string"},{"name":"cursor","description":"Created-at cursor of the last post from the previous page.","required":false,"type":"string"},{"name":"page_size","description":"Page size (default 5).","required":false,"type":"integer"}],"responses":{"success":{"type":"array","items":{"type":"object"}}}}},{"id":"fetch_post","title":"Get a single post","description":"Fetch one post by id. Requires a session when the post is paid — locked posts return file entries with empty content so gated media is never leaked; unlocked posts include full files. Archived posts return 404 unless the viewer is the owner.","actions":[{"id":"get_post","sourceId":"bitsimp_api","operationId":"getPost"}],"links":[{"origin":{"actionId":"fetch_post","fieldPath":"parameters.postId"},"target":{"actionId":"get_post","fieldPath":"parameters.postId"}}],"fields":{"parameters":[{"name":"postId","description":"Post id (UUID).","required":true,"type":"string"}],"responses":{"success":{"type":"object"}}}},{"id":"list_post_comments","title":"List comments on a post","description":"Fetch the newest-first, offset-paginated public comments for a post. Public read — no session required.","actions":[{"id":"list_comments","sourceId":"bitsimp_api","operationId":"listComments"}],"links":[{"origin":{"actionId":"list_post_comments","fieldPath":"parameters.postId"},"target":{"actionId":"list_comments","fieldPath":"parameters.postId"}},{"origin":{"actionId":"list_post_comments","fieldPath":"parameters.offset"},"target":{"actionId":"list_comments","fieldPath":"parameters.offset"}},{"origin":{"actionId":"list_post_comments","fieldPath":"parameters.limit"},"target":{"actionId":"list_comments","fieldPath":"parameters.limit"}}],"fields":{"parameters":[{"name":"postId","description":"Post id to fetch comments for (UUID).","required":true,"type":"string"},{"name":"offset","description":"Number of comments to skip.","required":false,"type":"integer"},{"name":"limit","description":"Maximum number of comments to return (default 10).","required":false,"type":"integer"}],"responses":{"success":{"type":"array","items":{"type":"object"}}}}},{"id":"get_my_balance","title":"Get the current user's balance","description":"Return the authenticated user's account id, npub, alias and full available-balance breakdown. Requires a valid session cookie (see the authenticate_* flows). Balance formula: availableBalance = earnedAmount − routingFees − pwbSpendings − withdrawnAmount − withdrawalFees.","actions":[{"id":"get_me","sourceId":"bitsimp_api","operationId":"getMe"}],"fields":{"parameters":[],"responses":{"success":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"npub":{"type":["string","null"]},"alias":{"type":["string","null"]},"availableBalance":{"type":"object"}},"required":["id","npub","alias","availableBalance"]}}}}]}