Developer and SDK Guide Template
Developer guide – setup, auth, multi-language quick start, errors, pagination, rate limits, webhooks, sandbox, versioning
使用方法: Use alongside a generated API reference to help developers integrate. Write the quick example first and test it with a new account; then errors, limits and webhooks. The main pitfall is code samples that do not run as written.
预览
Developer Guide: [Product name] API and SDKs
Complete guide for developers who integrate with an API or build on an SDK: concepts, setup, authentication, working code, error handling, limits, webhooks, testing, versioning and support. Based on common industry practice for developer documentation. Replace every
[bracketed]value and every row marked Example.
Document control
| Field | Value |
|---|---|
| Document ID | [DG-PRODUCT-001] |
| API version | [v2 (2026-09-01)] |
| SDK versions | [Python 4.1, JavaScript 5.0, Go 1.8] |
| Guide version | [0.1] |
| Status | [Draft / In review / Approved / Superseded] |
| Owner | [@devrel-owner] |
| Approvers | [@api-lead], [@security-reviewer] |
| Last updated | YYYY-MM-DD |
Approvals
| Role | Name | Decision | Date |
|---|---|---|---|
| API product owner | [@name] | [Approved / Rejected / Approved with comments] | YYYY-MM-DD |
| SDK maintainer | [@name] | [Decision] | YYYY-MM-DD |
| Security reviewer | [@name] | [Decision] | YYYY-MM-DD |
Revision history
| Version | Date | Author | Change summary |
|---|---|---|---|
| 0.1 | YYYY-MM-DD | [@name] | Initial draft |
| 1.0 | YYYY-MM-DD | [@name] | Example: Published with API v2 general availability |
| 1.1 | YYYY-MM-DD | [@name] | Example: Added Go samples and webhook signature verification |
Contents
1. Overview
The [Product name] API lets you [create and manage invoices, collect payments and receive status updates] from your own application. Official SDKs wrap the REST API for [Python, JavaScript and Go]; any language that can send HTTPS requests and parse JSON can use the API directly.
| You can | You cannot |
|---|---|
| Example: Create, update and send invoices | Change account billing settings (dashboard only) |
| Example: Receive webhook events for payment status | Access other accounts' data |
| [Capability] | [Limitation] |
2. Concepts
| Concept | Meaning | Example |
|---|---|---|
| Resource | An object with a stable ID and URL | inv_8f2c... at /v2/invoices/inv_8f2c... |
| Idempotency key | A client-chosen key that makes a retried request safe | Idempotency-Key: 6c1e-... |
| Environment | Separate data and keys for testing and live use | sandbox, live |
| Event | A record that something happened, delivered by webhook | invoice.paid |
| Expansion | Inline related objects in a response | ?expand=customer |
The main objects relate as follows. Use this model to decide which IDs to store in your own database.
All timestamps are ISO 8601 in UTC. Monetary amounts are integers in the smallest currency unit (for example cents) with an ISO 4217 currency code.
3. Setup
-
Create a developer account at [https://dashboard.example.com/signup].
-
In Developers > API keys, create a sandbox secret key.
-
Store it in an environment variable, never in source code:
export EXAMPLE_API_KEY="sk_sandbox_[...]" -
Install an SDK:
Language Requirement Install Python 3.10+ pip install example-sdk==4.1.*JavaScript / TypeScript Node.js 20+ npm install @example/sdk@5Go 1.22+ go get github.com/example/[email protected]
3.1 Environments and base URLs
| Environment | Base URL | Keys start with | Data |
|---|---|---|---|
| Sandbox | https://api.sandbox.example.com/v2 | sk_sandbox_ | Test data only; reset on request |
| Live | https://api.example.com/v2 | sk_live_ | Real customers and money |
The SDKs pick the base URL from the key prefix, so switching environments means switching keys. Keep separate keys per environment and per service so you can revoke one without affecting the others.
3.2 Recommended project setup
- Read the key from configuration at start-up and fail fast if it is missing.
- Create one client per process and reuse it; it keeps connections open.
- Turn on SDK debug logging only in development: it prints request paths and status codes but never the key.
4. Quick example
Create a customer and an invoice, then print the invoice URL.
import os
from example_sdk import Client
client = Client(api_key=os.environ["EXAMPLE_API_KEY"])
customer = client.customers.create(email="[email protected]", name="Ana Silva")
invoice = client.invoices.create(
customer=customer.id,
currency="EUR",
lines=[{"description": "Consulting, March", "amount": 120000}],
)
print(invoice.hosted_url)
import { Client } from "@example/sdk";
const client = new Client({ apiKey: process.env.EXAMPLE_API_KEY });
const customer = await client.customers.create({ email: "[email protected]", name: "Ana Silva" });
const invoice = await client.invoices.create({
customer: customer.id,
currency: "EUR",
lines: [{ description: "Consulting, March", amount: 120000 }],
});
console.log(invoice.hostedUrl);
curl https://api.example.com/v2/invoices \
-H "Authorization: Bearer $EXAMPLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customer":"cus_123","currency":"EUR","lines":[{"description":"Consulting, March","amount":120000}]}'
Expected output: a URL such as https://pay.example.com/i/inv_8f2c....
Open it to see the invoice in the sandbox.
5. Authentication
| Method | Use when | Header |
|---|---|---|
| Secret API key | Server-to-server calls from your backend | Authorization: Bearer sk_live_... |
| OAuth 2.0 authorization code with PKCE | Acting on behalf of another account | Authorization: Bearer <access token> |
| Restricted key | A service needs only some permissions | Same as secret key |
Rules for keys:
- Never ship a secret key in a mobile app or browser code.
- Use restricted keys with the minimum scopes, for example
invoices:write. - Rotate keys every [90] days and immediately if exposed; old keys can overlap with new ones for [24] hours.
For OAuth, redirect the account holder to
https://connect.example.com/oauth/authorize with your client_id, the
requested scope, a random state and a PKCE code_challenge. After
consent, exchange the returned code at POST /oauth/token for an access
token (valid [1 hour]) and a refresh token (valid [90 days], rotated on
each use). Store refresh tokens encrypted and revoke them when the
connected account disconnects your app.
A missing or invalid key returns 401 with error code authentication_failed.
6. Core tasks
6.1 Retrieve and update a resource
Retrieve an object by its ID, optionally expanding related objects, then
send only the fields you want to change. Fields you omit keep their value;
send null to clear an optional field.
invoice = client.invoices.retrieve("inv_8f2c", expand=["customer"])
client.invoices.update(invoice.id, due_date="2026-11-30")
6.2 Make a write request safe to retry
Send an idempotency key with every POST. If the network fails, retry
with the same key; the API returns the original result instead of
creating a duplicate.
await client.invoices.create(params, { idempotencyKey: crypto.randomUUID() });
6.3 Filter and expand
GET /v2/invoices?status=open&created[gte]=2026-10-01&expand=customer
returns open invoices created since 1 October with the customer inline.
6.4 Attach your own data with metadata
Every resource accepts up to [50] metadata key-value pairs (keys up to 40
characters, values up to 500). Use metadata to store your own order ID so
you can match webhook events to your records without an extra lookup.
Do not store personal or sensitive data in metadata; it appears in
exports and in the dashboard.
client.invoices.update("inv_8f2c", metadata={"order_id": "ORD-2026-00417"})
6.5 Search across resources
GET /v2/search/invoices?query=metadata['order_id']:'ORD-2026-00417'
returns matching invoices. Search results can lag writes by up to
[60 seconds], so use direct retrieval when you need the latest state.
7. Error handling
Errors use HTTP status codes and a JSON body:
{
"error": {
"type": "invalid_request",
"code": "parameter_missing",
"message": "The 'currency' parameter is required.",
"param": "currency",
"request_id": "req_91ab..."
}
}
| HTTP status | Type | Meaning | Retry? |
|---|---|---|---|
| 400 | invalid_request | Missing or invalid parameter | No; fix the request |
| 401 | authentication_failed | Missing, invalid or revoked key | No |
| 403 | permission_denied | Key lacks the scope | No |
| 404 | not_found | Resource does not exist in this environment | No |
| 409 | conflict | Idempotency key reused with different parameters | No |
| 429 | rate_limited | Too many requests | Yes, after Retry-After |
| 500, 502, 503 | api_error | Temporary problem on our side | Yes, with backoff |
Retry with exponential backoff and jitter: wait
seconds before attempt
, with and . Always log request_id.
8. Pagination
List endpoints return up to limit items (default 20, maximum 100) and
a cursor:
{ "data": [ ... ], "has_more": true, "next_cursor": "cur_3Jd..." }
Pass starting_after=<next_cursor> to get the next page. The SDKs
iterate automatically:
for invoice in client.invoices.list(status="open").auto_paging_iter():
process(invoice)
9. Rate limits
| Environment | Limit | Burst |
|---|---|---|
| Sandbox | 25 requests per second per account | 50 |
| Live | 100 requests per second per account | 200 |
Every response includes RateLimit-Limit, RateLimit-Remaining and
RateLimit-Reset. On 429, wait for the Retry-After seconds. Use
webhooks instead of polling to stay well under the limit.
10. Webhooks
- Register an HTTPS endpoint in Developers > Webhooks and choose events.
- Respond with
2xxwithin 10 seconds; process work asynchronously. - Verify the signature before trusting the payload:
from example_sdk.webhooks import verify
event = verify(payload=request.body,
header=request.headers["Example-Signature"],
secret=os.environ["EXAMPLE_WEBHOOK_SECRET"],
tolerance_seconds=300)
Failed deliveries are retried for [3 days] with increasing delay. Events
may arrive out of order or more than once; deduplicate by event.id and
check the resource's current state before acting.
| Event | Sent when |
|---|---|
invoice.finalized | An invoice can no longer be edited |
invoice.paid | Payment succeeded |
invoice.payment_failed | A payment attempt failed |
| [event] | [Trigger] |
11. Testing and sandbox
The sandbox is fully isolated from live data. Use these test values:
| Value | Behaviour |
|---|---|
Card 4242 4242 4242 4242 | Payment succeeds |
Card 4000 0000 0000 0002 | Payment is declined |
Email ending [email protected] | Invoice email bounces |
Forward webhooks to your laptop with example-cli listen --forward-to localhost:3000/webhooks, and trigger events with example-cli trigger invoice.paid.
11.1 Go-live checklist
| # | Check | Done |
|---|---|---|
| 1 | Live keys stored in the secret manager, not in code or CI logs | [ ] |
| 2 | Every write request sends an idempotency key | [ ] |
| 3 | Webhook signatures are verified and events deduplicated by ID | [ ] |
| 4 | 429 and 5xx are retried with backoff; other errors are logged with request_id | [ ] |
| 5 | API version pinned in configuration | [ ] |
| 6 | Alerting on webhook delivery failures and error rate | [ ] |
| 7 | Tested against the sandbox scenarios in this section | [ ] |
12. SDK reference conventions
| HTTP | Python | JavaScript | Go |
|---|---|---|---|
POST /v2/invoices | client.invoices.create() | client.invoices.create() | client.Invoices.Create() |
GET /v2/invoices/{id} | client.invoices.retrieve(id) | client.invoices.retrieve(id) | client.Invoices.Get(id) |
Field hosted_url | hosted_url | hostedUrl | HostedURL |
SDK errors raise or return typed exceptions named after the error type,
for example RateLimitedError. Each SDK follows semantic versioning.
13. Versioning and deprecation
The API version is a date sent in the Example-Version header; your
account default is set when you create it. Additive changes (new fields,
new endpoints, new event types) can happen at any time, so parse JSON
tolerantly. Breaking changes ship only in a new version, announced at
least [12 months] before the old version is retired.
| API version | Released | Status | Retirement date |
|---|---|---|---|
| Example: 2026-09-01 (v2) | 2026-09-01 | Current | None planned |
| Example: 2024-03-15 (v1) | 2024-03-15 | Deprecated | 2027-09-30 |
| [Version] | YYYY-MM-DD | [Current / Deprecated / Retired] | YYYY-MM-DD |
Calls to a deprecated version return a Deprecation header with the
retirement date, so you can detect old integrations from your own logs.
14. Migration notes
| v1 | v2 | Action |
|---|---|---|
Example: amount as decimal string | amount as integer in minor units | Multiply by 100 for EUR, USD |
Example: Offset pagination (page) | Cursor pagination (starting_after) | Use SDK auto-paging |
| Example: Unsigned webhooks | Signed webhooks | Add signature verification |
Full details: [Migration Guide v1 to v2].
15. Best practices
- Keep keys in a secret manager and use restricted keys per service.
- Send an idempotency key with every write request.
- Handle
429and5xxwith backoff; never retry4xxother than429. - Use webhooks for state changes instead of polling.
- Store our resource IDs in your database rather than matching on names.
- Pin the API version and SDK major version; upgrade deliberately.
- Set client timeouts (for example 10 s connect, 30 s read) so a slow network does not block your workers indefinitely.
- Log request IDs, not request bodies, to avoid storing personal data and secrets in your logs.
- Subscribe to the changelog feed so deprecations never surprise you.
16. Support
| Need | Where |
|---|---|
| API status and incidents | [https://status.example.com] |
| Questions and examples | [Developer forum URL] |
| Bugs in an SDK | Issue tracker in the SDK repository |
| Account or production issues | [[email protected]] |
Include the request_id, API version, SDK name and version, and a
minimal code sample. Never send secret keys.
Appendix A. Glossary
| Term | Meaning |
|---|---|
| Minor unit | Smallest unit of a currency, for example cents for EUR |
| Idempotency | Property that repeating a request has the same effect as sending it once |
| Scope | A named permission attached to a restricted key or OAuth token |
| Cursor | Opaque value that marks a position in a list for pagination |
| [Term] | [Meaning] |
Standard and licence note
Based on common industry practice for API and SDK developer documentation (guides that combine concepts, quick starts, task examples and operational rules, with a separate generated API reference). This template is original text written for this collection. Template licence: MIT.
相关模板
Administrator Guide Template (ISO/IEC/IEEE 26514)
Admin guide – roles, architecture, access, backup/restore, monitoring, maintenance, scaling, security ops, DR, audit
文档与支持Installation and Configuration Guide Template (ISO/IEC/IEEE 26514)
Install guide – requirements, checklist, per-platform steps, verification, config parameters, upgrade, uninstall, hardening
文档与支持Migration Guide Template
Upgrade/migration guide – who is affected, breaking changes table, timeline, checklist, steps, before/after code, rollback