Matthew Pettigrew

When the documentation is the product demo

Strike's API had no sales team and no trial. A developer evaluating it decides within ten minutes whether integrating bitcoin, Lightning and stablecoin payments was tractable, and the documentation was the surface for making that decision.

The situation

For a payments API, documentation is the pitch, the demo, and the evaluation all at once. Nobody books a call before deciding whether an API is worth the effort. They open the docs, skim for ten minutes, and either start building or close the tab.

Strike’s API docs had additional challenges. A developer arriving from Stripe or PayPal carries a mental model that does not necessarily transfer to Bitcoin. Lightning invoices expire in seconds, on-chain transactions need confirmations, the exchange rate moves between quoting a price and being paid, and settlement currency varies by region. Each of those is a place where an assumption carried over from a card processor produces a bug that loses money in production.

There was also an underlying problem with who could fix the docs. The people who understood the API best had built it, but there was a lack of perspective for newcomers to the space. While the reference documentation was accurate and complete, it needed to address the nuances of working with payment rails and digital assets that did not have direct equivalents in legacy finance.

The strategy

I built a walkthrough layer above the reference, organised around decisions instead of endpoints: receiving payments, sending payments, directing payments to third parties, making payouts, exchanging currencies, and OAuth Connect.

Three rules held across all six operations. The first substantive thing on each walkthrough is an explanation of what it is and how it works. Second, every walkthrough documents the failure as well as the happy path, because every surprise found in staging is a surprise that could have been one sentence. And third, every constraint carries its reason, because a limit stated plainly is an obstacle to route around, while a limit with a reason is something developers design correctly against.

Sitting outside engineering helped substantially. Someone who has to ask why a quote expires in thirty seconds is the person who notices that it needs explaining.

Selected work

docs.strike.me · The decision, before any code docs.strike.me ↗
TypeInvoiceReceive request
Supported railsBolt11 Lightning invoiceOn-chain or Bolt11 Lightning invoice
Payment amountRequiredOptional
Settlement currencyBitcoin or USDBitcoin or USD
Currency conversionGuaranteed rate for 30 secondsMarket rate at time of payment
Under/overpaymentsImpossiblePossible, but at your discretion
Use casesE-commerce transactions, subscriptions, or fixed-fee servicesDonations, pay-what-you-want services or pay-as-you-go services

Two primitives that look interchangeable on an endpoint list, where picking wrong is expensive to unwind after you have shipped. “Under/overpayments: impossible” is a consequence that needs to be addressed upfront, and stating it that way lets a developer make the call from this table alone.

docs.strike.me · A constraint with its reason attached docs.strike.me ↗

Invoices currently can only be fulfilled via the Lightning Network, as regular on-chain transactions have longer settlement periods, which makes holding a bitcoin-to-dollar quote unaffordable.

Please note that for bitcoin-denominated invoices, the conversionRate will simply be 1 and the expiration period will be 1 hour (3,600 seconds). For cross-currency invoices, the expiration time will be 30 seconds.

The original documentation stated the thirty seconds and stopped. Developers read it as an arbitrary limit and asked whether it could be raised, which was a recurring support thread. The first paragraph was added to answer the question underneath: somebody is carrying exchange-rate risk for the length of that quote. Once that is on the page, the thirty seconds stops being negotiable and starts being a number people design their retry logic around.

docs.strike.me · The trap nobody would have caught docs.strike.me ↗

Please note that the webhook subscription response doesn’t contain the new invoice state, rather it describes that the state has changed. To request the new state of the invoice, use the find invoice endpoint and specify the relevant invoiceId.

I worked directly with the engineers who created the API to determine what the webhook payload contained, assumed the obvious answer, and was wrong. Code written on that assumption fails silently, which is the expensive kind. The paragraph is here because the person writing the documentation was not the person who built the endpoint, and had to ask.

Outcome

A documentation set covering the full surface of the API: six decision-led walkthroughs, OAuth Connect, webhooks, sandbox, rate limits and API key management, plus the reference.

The walkthroughs are backed by a gallery of working integrations built on the API, each with a public repository a developer can read: invoicing, bill splitting, paywalls for URLs and email, paid polls, an in-person checkout, and an OAuth reference implementation. Documentation that ends in someone else’s shipped code is doing its job.

Strike’s API is now one of the most established ways to accept bitcoin, Lightning and stablecoin payments and settle in local currency. What that has produced commercially is Strike’s to disclose. What I can point at is the documentation a developer reads before deciding whether to try, and the fact that they kept building.

Source: Example apps, Strike API documentation.


Written as Senior Content Manager at Strike, 2022 to 2025. The documentation at docs.strike.me was entirely mine during my tenure. Sections may have been revised since.