Build the mental model
So far every code example in this course has called `fetch` directly, building headers and parsing responses by hand. That is the raw API approach: full control, no extra dependency, but you are personally responsible for auth headers, retry logic, pagination, and keeping up with the provider's response shape.
Many providers also publish an official SDK, a library that wraps the raw HTTP calls behind typed method names. Instead of constructing headers yourself, you call something like `stripe.charges.create({ amount, currency })` and the SDK handles auth, retries, pagination, and often validation internally.
| Aspect | Raw API vs SDK |
|---|---|
| Control | Raw API -- full control over every request and response. SDK -- limited to whatever the SDK's method design allows. |
| Boilerplate | Raw API -- you write headers, parsing, and error handling yourself. SDK -- often just one method call. |
| Dependencies | Raw API -- no extra dependency needed. SDK -- one more library to install, update, and trust. |
| Versioning | Raw API -- new provider features are usable immediately. SDK -- often lags behind the SDK's own release cadence. |
| Pagination handling | Raw API -- you implement paging logic yourself. SDK -- often handled automatically via an iterator or helper method. |
Neither option is universally correct. The right choice depends on your language ecosystem, how mature and well-maintained the specific SDK is, and how much boilerplate your project can justify writing and maintaining itself.
RAW API PATH VS SDK PATH
------------------------
RAW API PATH
------------
App -> build headers/body -> fetch() -> parse response -> result
SDK PATH
--------
App -> sdk.charges.create(params) -> [auth+retry+parse inside] -> resultConnect it to a real scenario
`rawApiCharge` shows the raw path: it manually builds an `Authorization` header from a passed-in API key, serializes a JSON body, and returns a `parsedResult` standing in for a parsed real HTTP response. Every piece of that plumbing is the caller's responsibility.
`sdkCharge` shows the same logical operation the way an SDK would expose it: the caller passes only the parameters that matter and gets back the same shaped `parsedResult`. There is no visible `apiKey` parameter or header construction at all.
Both functions produce the identical logical charge result. The difference the output makes visible is entirely in the boilerplate the caller has to write and maintain: explicit and inspectable in the raw version, hidden and delegated in the SDK version.
Try the working example
function rawApiCharge(apiKey, amount, currency) {
const headers = {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
};
const body = JSON.stringify({ amount, currency });
return {
via: "raw",
headers,
body: JSON.parse(body),
parsedResult: { id: "ch_raw_1", amount, currency, status: "succeeded" }
};
}
function sdkCharge(amount, currency) {
return {
via: "sdk",
parsedResult: { id: "ch_sdk_1", amount, currency, status: "succeeded" }
};
}
console.log(rawApiCharge("sk_test_123", 2000, "usd"));
console.log(sdkCharge(2000, "usd"));raw -> { via: 'raw', headers: { Authorization: 'Bearer sk_test_123', 'Content-Type': 'application/json' }, body: { amount: 2000, currency: 'usd' }, parsedResult: { id: 'ch_raw_1', amount: 2000, currency: 'usd', status: 'succeeded' } }
sdk -> { via: 'sdk', parsedResult: { id: 'ch_sdk_1', amount: 2000, currency: 'usd', status: 'succeeded' } }5-minute try-it
Run both `rawApiCharge` and `sdkCharge` and count the lines of code each needs. Then decide, for a new project integrating a provider with pagination, whether you would choose the raw API or an SDK, and write down why.
One important caution
Declaring SDKs universally "slower" or "worse" -- mature SDKs usually handle production-grade retry and auth logic well
Assuming a raw implementation has full feature parity and skipping the provider's docs while self-implementing pagination or retries
Stripe API Libraries — API Integration & Webhooks