{"store":"Ghost Signals Records","catalog":"https://records.ninja-portal.com/api/store","steps":["GET https://records.ninja-portal.com/api/store and pick a sku.","POST https://records.ninja-portal.com/api/store/<sku>/buy with JSON {\"from\": \"<your wallet address>\", \"email\": \"<optional>\"}; the 402 reply carries payment.payTo, payment.amountMicro, payment.asset (USDC on Base, chain 8453) and payment.calldata for the transfer.","Either send exactly that amount of USDC to payTo from the wallet you named (you pay the gas), or, with no ETH at all: sign payment.gasless.typedData (EIP-712, your address in message.from) with eth_signTypedData_v4 and POST {\"from\", \"signature\"} to payment.gasless.submitUrl; the store submits it and pays the gas. payment.gasless.enabled is false when the relayer is off or dry.","POST https://records.ninja-portal.com/api/purchase/<publicId>/tx with {\"hash\": \"<tx hash>\"}. If the purchase named your wallet (\"from\"), the store's chain watcher also settles it on its own; a purchase opened without \"from\" is settled only by this call, since the watcher cannot tell whose transfer it is.","GET https://records.ninja-portal.com/api/purchase/<publicId>: when state is \"paid\", purchase.download is your zip (mp3s, cover art, README)."],"rules":["One transfer pays for one purchase. A transfer mined before the purchase was opened does not count.","Downloads are for personal listening; see README.txt in the zip.","Errors: a 4xx with {\"error\"} or {\"ok\": false, \"reason\"} is yours to fix (bad address, amount, signature or hash); a 503 means a provider or key on our side failed, and on /authorize it carries a Retry-After header (send_reverted is a 409: USDC refused that authorization, so sign a fresh one rather than resend it); a 429 carries retryAfterSec and a Retry-After header, per lane (checkout, claims, the ATM legs are throttled separately).","The gasless authorization expires 30 minutes after it is issued; GET https://records.ninja-portal.com/api/purchase/<publicId> issues a fresh one while the purchase is still awaiting.","Name your wallet when you open the purchase. Without \"from\", payment.gasless.payer is null and typedData.message.from is the zero address as a placeholder: replace it with your own address before signing, and the signer becomes the payer. The zero address itself is refused as a wallet.","Unknown ids under /api/ answer 404 with {\"error\": \"not found\"}; a purchase id is 16 to 32 URL-safe characters."]}