Product job specs keep asking for the same thing in different words: "comfortable working with APIs", "technical", "experience with third-party integrations". Nobody expects a product manager to write the integration. What they want is someone who can open a provider's documentation, work out what the API can do for the product, what it would take, and what could go wrong, then have a useful conversation with engineers about it.
The first five parts of this series explained how APIs work, using a weather API I chose. This part is about someone else's API, and the skill that sits on top of everything else: reading the docs. The example is a page many product people will meet sooner or later, Stripe's Create a refund. Stripe's docs are widely copied, so if you can read this page, you can read most of them. When you're done, there's a quick challenge to try it out.
What the job spec really means
What the job spec really means
| The job spec says | What they want to know | How to show it |
|---|---|---|
| "Comfortable working with APIs" | You can open a provider's docs and tell what it can and can't do, without waiting for an engineer. | Talk through one API you've read: what it offers, what it needs, what can go wrong. |
| "Technical product manager" | You can hold a design conversation with engineers and write tickets they don't have to rewrite. | Bring a user story whose acceptance criteria came straight from the docs. |
| "Experience with third-party integrations" | You know the risks of building on someone else's product: limits, costs, outages, versions. | Name the questions you asked before an integration, and one that saved you. |
| "Data-literate" | You can read JSON and know a field from a value, an ID from a name. | Point at a response and say which fields the customer would see. |
| "Platform or API product" | The API is the product, and developers are the customers. | Judge the docs themselves: could a new developer make their first call in ten minutes? |
All five come down to the same skill. You don't need to memorise anything. You need a way of reading that turns a page of technical reference into product decisions, and that's what the rest of this part is.
Seven questions for any API docs
API documentation isn't meant to be read from top to bottom, like a book. It's a reference, more like a dictionary. I read it with seven questions in mind, roughly in this order, and stop when I have what I need:
Seven questions for any API docs
- 1What does it know about?
The nouns in the sidebar: the resources or objects.
Refunds: Refunds, charges, customers, disputes
- 2What can I do to them?
The verbs under each noun: the endpoints.
Refunds: Create, retrieve, update, list, cancel
- 3What must I send?
Parameters: required or optional, their types, units and defaults.
Refunds: A payment intent, and an amount in pence
- 4What comes back?
The object in the response, and every status it can be in.
Refunds: A refund with an ID and a status
- 5What can go wrong?
The errors page and the error notes on each endpoint.
Refunds: Refunding more than is left
- 6What happens later?
Webhooks or events: what the API tells you without being asked.
Refunds: refund.failed, days afterwards
- 7What are the rules?
Keys, test mode, limits, versions, pricing and terms.
Refunds: Test keys, dated versions, rate limits
The first two take a couple of minutes and tell you whether the API is even worth a closer look. The last two are where the hidden work lives, and they're the ones most often skipped.
A docs page, part by part
Most API reference pages share a layout: a sidebar of everything the API offers on the left, the explanation and parameters in the middle, and example code on the right. Here's a simplified copy of Stripe's Create a refund page. Pick a number to see what each part is and what to read it for.
A docs page, labelled
Core resources
Create a refund
When you create a new refund, you must specify a Charge or a PaymentIntent object on which to create it.
You can optionally refund only part of a charge. You can do so multiple times, until the entire charge has been refunded. Once entirely refunded, a charge can't be refunded again.
POST /v1/refunds
Parameters
payment_intentstring- The ID of the PaymentIntent to refund.
chargestring- The ID of the charge to refund.
amountinteger- A positive integer in the smallest currency unit: how much of the charge to refund. Up to the amount not yet refunded.
reasonenum- One of
duplicate,fraudulentorrequested_by_customer. metadataobject- Key-value pairs of your own, stored with the refund.
+ More parameters
Example request
curl https://api.stripe.com/v1/refunds \
-u "sk_test_DEMO-KEY-0000-NOT-REAL:" \
-d payment_intent=pi_DEMO123 \
-d amount=1250 \
-d reason=requested_by_customer \
-d "metadata[order_id]"=A1042Response
{
"id": "re_DEMO123",
"object": "refund",
"amount": 1250,
"currency": "gbp",
"payment_intent": "pi_DEMO123",
"reason": "requested_by_customer",
"status": "succeeded",
"created": 1793923200,
"metadata": { "order_id": "A1042" }
}- 1
The sidebar: nouns, then verbs
The menu lists the things the API knows about (resources, or objects): charges, customers, disputes, refunds. Under each are the things you can do to them: create, update, retrieve, list, cancel.
Read it for: the shape of the whole product in a minute. If something your feature needs isn't a noun or a verb here, the API probably can't do it.
- 2
The description: business rules
The short paragraph under the title is where the rules hide. This one has three: you can refund part of a payment, you can refund more than once, and you can never refund more than was paid.
Read it for: acceptance criteria. Each rule is one waiting to be written, along with what the customer sees when it's broken.
- 3
The method and path: what, to what
POSTmeans create (Part 2), and/v1/refundsis the address, with the version at the front. The full address is the base URL, given once at the top of the docs (https://api.stripe.com), plus this path.Read it for: whether you're reading or changing something. A
POSThere moves real money, so it needs permissions, an audit trail and a confirm step. - 4
Parameters: what you can send
Each one has a name, a type and a description, and most docs label the ones that are required. Here none is required on its own, but the description says you must send a payment intent or a charge. Read the words, not just the labels.
Read it for: what your product must already know before it can make the call. If you don't store the payment intent ID today, that's a piece of work.
- 5
Types and units: the small print
"Integer in the smallest currency unit" means pence:
1250is £12.50, not £1,250. Leaveamountout and the whole amount still left is refunded.Read it for: defaults. A missing amount in a "refund one item" feature refunds the whole order, which is exactly the kind of bug a sharp ticket prevents.
- 6
Enums: a fixed list of choices
An enum accepts only the values listed. Further down, the docs add that
fraudulentalso puts the card and email on Stripe's block lists.Read it for: product decisions. These three values are your reason dropdown, and
fraudulentshould never be its default. - 7
The example request: a whole call
-usends the key (Part 4), andsk_test_says it's a test key, so no real money moves. Most docs show the same call in several languages, and many have a "try it" button.Read it for: the sandbox. A test mode means the team can build and demo the feature in sprint review without touching a real card.
- 8
The response: what comes back
A refund object: an ID to save (
re_…), the amount, your ownmetadata, a timestamp in seconds since 1970 and, most importantly, astatus. The docs list five of those, and only one says the money is back.Read it for: states. Every status is a screen, a message or an email to design, which is the table below this one.
Questions 1 and 2: the nouns and the verbs
The sidebar is the fastest way to see what an API can do. The nouns (Charges, Customers, Disputes, Refunds) are the things it knows about. Open one and the verbs underneath are what you can do to them. Here's the whole Refunds section, translated into things a product could do:
Every verb in the Refunds section
| Endpoint | What it does | What you could build |
|---|---|---|
POST /v1/refunds | Create a refund | A refund button in the customer service tool, or self-serve refunds in the customer's account |
GET /v1/refunds/:id | Retrieve one refund | A refund's latest status on the order page |
POST /v1/refunds/:id | Update a refund (only its metadata) | Adding the support ticket number after the event |
GET /v1/refunds | List refunds, filtered by charge, payment or date, a page at a time | A refund history on the order, or a daily report for finance |
POST /v1/refunds/:id/cancel | Cancel a refund that's waiting for the customer to act | An "undo" for a refund that hasn't gone through |
This is the step that answers "what could this API do for us?", and it's worth writing down even when the answer seems obvious. Five endpoints became six possible features, from a refund button for the support team to a report for finance. It also shows the limits: you can only update a refund's metadata, so a refund sent for the wrong amount can't be edited, only followed by another refund.
Question 3: what must I send?
Parameters are the details of the order. For each one, I look for four things:
- Is it required? Usually a label next to the name. But read the descriptions too: Create a refund marks neither
payment_intentnorchargeas required, because you have to send one or the other. - What type is it? A string (text), an integer (whole number), a boolean (true or false), an enum (a fixed list) or an object (a group of values).
- What are the units? "Smallest currency unit" means pence, so
1250is £12.50. Dates are often seconds since 1 January 1970, not a date you'd recognise. - What happens if I leave it out? Leave out
amountand the whole amount left on the payment is refunded. Defaults are decisions someone else made for you.
The question behind all four is: does our product already know this? Stripe needs the ID of the original payment. If your order system doesn't save it, that's work to add to the estimate before anyone writes a line of refund code.
Question 4: what comes back?
The example response shows the object you get back. Three things in it matter most to a product manager: the ID (your product saves it to find the refund again), any field a person will see, and the status.
Statuses are where the design work hides. The docs list five for a refund, and "refunded" is only one of them:
One status, one design decision
| Status | What it means | What the customer sees | What the team does |
|---|---|---|---|
pending | Sent, waiting for the bank or payment method. The refund's pending_reason says why. | "Your refund of £12.50 is on its way. It can take a few working days to reach your account." | Nothing yet. Wait for Stripe to say it's changed. |
requires_action | Some payment methods can't refund on their own, so the customer has to do something, such as give bank details. | "Check your email to finish your refund." | Watch for ones that sit there. Only these can be cancelled. |
succeeded | The refund went through. | "Refunded £12.50." | Close the ticket. |
failed | It bounced, for example because the card has expired or been cancelled. failure_reason says which. | "We couldn't refund your card. We'll be in touch to refund you another way." | Get alerted, and refund another way. |
canceled | It was cancelled before it went through. | "Your refund was cancelled." (and why) | Record who cancelled it and why. |
If someone says "it's just one API call", the status list is the polite way to show it isn't. Each row is a message to write, a state to design or an alert to set up.
Question 5: what can go wrong?
Every docs site has an errors page listing its status codes (Part 2) and what an error message looks like. Then each endpoint adds its own: Create a refund fails if the payment has already been fully refunded, or if you ask for more than is left.
I turn each one into a sentence for the ticket: "If the agent enters more than the amount left, show 'You can refund up to £X' and don't send the request." Catching it in your own product first is kinder to the customer than passing on the API's error.
Question 6: what happens later?
A refund isn't over when the API answers. It can sit at pending for days, then succeed, or fail because the card was cancelled. Nobody is asking the API at that moment, so the API tells you instead, through webhooks (Part 1). Stripe calls these events, and the ones for refunds include refund.created, refund.updated and refund.failed.
This is the most commonly missed part of an integration. If nobody listens for refund.failed, the customer is told their money is on its way, and it never arrives. Look for the events section of any docs, and for each event ask: who needs to know, and what do we do?
Question 7: what are the rules?
Around the endpoints sit pages that apply to every call. They're easy to skip and expensive to miss:
The pages around the endpoints
How you prove who you are. Stripe has secret keys that start sk_, with separate test and live keys.
Ask: Where will the secret key live, and who can see it?
The status codes the API uses, and the shape of an error message.
Ask: What does the customer see for each one?
How many requests you can make in a period, and what happens after (usually a 429).
Ask: Will a bulk job, or Black Friday, hit it?
Send a unique Idempotency-Key header with a request, and a retry won't do the same thing twice.
Ask: Can a double-click refund someone twice?
The messages the API sends you when something changes: refund.created, refund.updated, refund.failed.
Ask: Are we listening, and who hears about failures?
Lists come back a page at a time: limit, starting_after, has_more.
Ask: Does our report fetch every page, or just the first?
Stripe's versions are dates with a name, such as 2026-09-30.endive, and each account is pinned to one.
Ask: Which version are we on, and what changed since?
A sandbox with test keys and test cards, where nothing real happens.
Ask: Can we demo it without real money?
What changed and when, including anything being retired.
Ask: Is anything we use going away?
Then there's what the docs don't say. Pricing, support and uptime promises are usually on the provider's main website or in your contract, and Part 4 has a checklist of questions to ask before you integrate.
From docs to a user story
Here's how the reading turns into a ticket. Almost every line of the acceptance criteria comes from something on the docs page.
As a customer service agent, I want to refund one item from an order, so that the customer gets their money back without me refunding the whole order.
- The amount starts at the item's price and can't be more than the amount left to refund. If it is, the agent sees "You can refund up to £X" and nothing is sent. (Parameters: amount, and the description's rules.)
- The agent must pick a reason: duplicate, fraudulent or requested by customer. Fraudulent asks for confirmation, because it also blocks the card. (The reason enum.)
- The order number and support ticket number are saved with the refund. (Metadata.)
- The order page shows the refund's status and updates when Stripe reports a change. If a refund fails, the agent's team is alerted and the customer is told how they'll be refunded instead. (Statuses and events.)
- Clicking Refund twice creates one refund, not two. (Idempotency.)
- Tested end to end in Stripe's test mode before release. (Test keys.)
Engineers will add detail, but a ticket like this starts the conversation in the right place, and that's what "comfortable with APIs" looks like in practice.
Talking about it in an interview
"Tell me about a time you worked with an API" is a common interview question for product roles. A good answer shows how you think, not how much code you know. I'd structure it like this:
- The goal: what the product needed, in customer terms.
- What I read: the docs, and what they told me the API could and couldn't do.
- What I found: the hidden work, such as a status nobody had designed for, an ID we weren't saving or a rate limit we'd hit at peak.
- What I decided: how it shaped the scope, the tickets or the plan.
- What happened: the outcome, and what I'd check earlier next time.
If you haven't worked on an integration yet, read one docs site properly (the list below is a good start) and talk through what you'd build with it, using the seven questions. Being able to say "I read Stripe's refund docs and the thing I'd flag first is the failed status" is a stronger answer than most.
Test yourself
Pick a question to see my answer.
Test yourself
1A docs page says amount is "an integer in the smallest currency unit". A customer is owed £8.99. What do you send?
899. Pence, not pounds, and a whole number, so no decimal point.
2The API answered with "status": "pending". Can you tell the customer they've been refunded?
Not yet. Tell them it's on its way. It could still fail, so listen for the event that says it has changed.
3The sidebar has no Subscriptions section. What does that probably tell you?
That the API can't manage subscriptions, or does it under another name. Search the docs before you plan around it, and ask the provider if you still can't find it.
4An engineer says "that endpoint isn't idempotent". Why should you care?
A retry, or a customer clicking twice, could do the thing twice: two refunds, two orders, two emails. Ask how the team will stop that.
5A field you rely on is marked deprecated. What do you do?
Check the changelog for when it goes and what replaces it, then put the move on the roadmap before the date, not after.
Practise on real docs
The quickest way to practise is the API docs challenge: six product requests, such as "refund one item when all I have is the customer's email", and a page of Stripe's real endpoints. You pick the endpoints each one needs, then see the calls in order, what each returns and the outcome. It takes about ten minutes.
After that, try a whole docs site. These are all public and free to read:
- Open-Meteo: the weather API from this series. No key, and you can try requests right on the page.
- Stripe API reference: payments. Try the seven questions on Customers or Disputes.
- GitHub REST API: issues, pull requests and more. A good one for pagination and rate limits.
- Twilio Messaging: sending texts. Look for the statuses a message goes through, and the webhooks that report them.
Pick one, give yourself twenty minutes and write down one line for each of the seven questions. That page of notes is most of what an engineer would want from you at the start of an integration.
Words you'll see in docs
Words you'll see in docs
- API reference
The part of the docs that lists every endpoint. Guides and tutorials sit alongside it.
"It's in the API reference, under Refunds."
- Resource (or object)
A kind of thing the API knows about: a refund, a customer, an order.
"Is there a resource for subscriptions?"
- Endpoint
One thing you can do: a method and a path, like POST /v1/refunds.
"Which endpoint do we call?"
- Path, query and body parameters
Values in the address (/refunds/re_123), after the ? (?limit=10), or sent inside the request.
"Is the ID a path parameter?"
- Enum
A field that only accepts values from a fixed list.
"What are the enum values for reason?"
- ID
The API's own unique reference for a thing, like re_DEMO123. Your product saves it to find the thing again.
"Do we store the payment intent ID?"
- Metadata
Your own labels stored with an object, such as your order number.
"Put the ticket number in metadata."
- Idempotency key
A unique value sent with a request, so a retry can't do the same thing twice.
"Are refunds idempotent?"
- Cursor pagination
Getting a long list a page at a time, starting after the last item you saw.
"We only read the first page."
- Sandbox (or test mode)
A copy of the service where nothing is real.
"Does it work in the sandbox?"
- SDK (or client library)
Ready-made code from the provider, so engineers don't write each request by hand.
"Is there a Python SDK?"
- OpenAPI spec
The whole REST API described in a file that tools can read, often used to build the docs themselves.
"Can we generate the client from the OpenAPI spec?"
- Deprecated
Still works, but going away. Stop using it.
"That field's deprecated in the new version."
- Breaking change
A change that stops existing integrations working, which is why versions exist.
"Is the upgrade a breaking change?"
That's the end of the series. If you've read all six parts, you know what an API is, how a request and response work, how an answer becomes a page, how keys and limits work, what a real integration looks like, and how to read the docs for the next one. For the other kind of API you'll meet in docs, carry on with GraphQL for product managers.