Freight emissions API vs SDK: when to use which, and what to ask vendors
Most emissions vendors push SDKs in their marketing because SDKs make better case studies. "Three lines of code and you’re live" reads better in a landing page than "here’s a Postman collection." But for a meaningful share of real freight-emissions integration patterns, the raw REST API is what you actually want, and the SDK adds dependency surface that buys you nothing. After running the EcoFreight API for two years and integrating against six other emissions vendors’ SDKs and APIs at various points, here is the honest decision framework I use. And if your vendor’s SDK is the only way to integrate with their service — that’s a red flag.
I run the engineering side of EcoFreight: the calculator API, the calculation engine, the data-ingestion pipelines that pull GLEC Framework v3.2 factor updates and methodology revisions into production. This post is the conversation I have with prospective customers when they ask which integration path makes sense. There’s no universal right answer; there are right answers for specific contexts, and the wrong choice gets locked in for years because integration code is sticky. For author background see my profile.
The vendor-SDK incentive problem
The reason SDKs get pushed in vendor marketing isn’t that they’re always better. It’s that they create a deeper integration commitment. An SDK in your codebase imports a vendor library, links against vendor types, and ties your build pipeline to vendor releases. Migrating away from a vendor whose SDK you’ve integrated against is a 3–6 month refactor. Migrating away from a vendor whose REST API you call via your own thin HTTP client is a 2–3 day rewrite, max.
That asymmetry is what makes vendor marketing teams prefer the SDK story. From a vendor’s perspective, an SDK customer is a customer. A raw-API customer is a maybe-customer who’s also evaluating your three competitors. The marketing-page bias toward SDKs is rational from the vendor’s side. It is not necessarily rational from the integrator’s side.
To be explicit: I’m on the vendor side of the EcoFreight conversation. My commercial interest is roughly aligned with pushing customers into deeper integration. I’m writing this anyway because the customers who choose the right integration pattern for their actual use case stick around longer than the ones who got talked into the wrong one.
When SDK is the right choice
There are real cases where an SDK earns its dependency weight.
Greenfield apps with a clear long-term commitment to the vendor. If you’re building a new TMS or shipper portal where emissions are a core feature, not a peripheral one, and you’ve done your vendor due diligence and you’re confident this is a 5+ year relationship, the SDK saves you from re-writing boilerplate. Type-safe data models, built-in retry logic, paginated-response handling, OAuth flow, instrumentation hooks — all genuinely useful.
Languages with strong type safety where compile-time validation against the API surface matters. TypeScript, Kotlin, Rust, Swift, Go. The SDK’s type definitions catch a real class of integration bugs at compile time that would otherwise surface as 422 responses in production. If you’re writing in one of these languages and the SDK has well-maintained types, the friction reduction is substantive.
When you want compile-time validation against changes in the API surface. An emissions API will evolve. Factor tables update, new modes are added, deprecated fields move toward retirement. A versioned SDK with explicit type definitions makes those changes visible at SDK-upgrade time: the upgrade fails to compile because the field you’re relying on was renamed. With raw REST, you discover the same change in production when a response shape changes. The SDK is a forcing function for upgrade discipline.
When the vendor publishes the SDK as the canonical interface. Some specialised emissions vendors expose features in the SDK that aren’t available via the raw HTTP API — things like local caching, offline computation, batch optimisation. If those features matter to you and they only ship via the SDK, you’re paying the SDK’s dependency cost for the features.
When the raw REST API is better
Five patterns where the SDK’s overhead is wasted weight.
Webhook handlers. When you’re receiving a webhook from your TMS or your shipment-tracking provider, you have a small payload, you make one synchronous emissions calculation call, and you return. A 5-line HTTP POST with a JSON body and a JSON response is the right tool — in our case the p50 round trip is around 42 ms and the JSON response is roughly 480 bytes. Importing a 200KB SDK to make that single call is mass overhead. Cold-start time in serverless environments matters, and the SDK’s import cost dominates the actual computation time.
Serverless functions. AWS Lambda, Cloudflare Workers, Vercel Functions. Cold-start time is the operative constraint. The smaller your function bundle, the faster your p50 invocation latency. Most emissions SDKs ship with dependencies that add 50–500KB to the function bundle and 100–500ms to cold start. A native HTTP fetch call adds zero to either. For high-frequency serverless workloads, the raw API is the obvious pick.
Batch ETL. When you’re running a nightly job that calculates emissions for 50,000 shipments and writes to a data warehouse, the SDK doesn’t help. You’re writing the orchestration logic yourself anyway, you want explicit control over rate limiting and retry behaviour, and you don’t need the SDK’s type-safety scaffolding because you’re working in a script context where the input/output shapes are stable across runs.
Polyglot environments. If your platform team writes Python, your data team writes Spark in Scala, your services team writes Go, and your frontend writes TypeScript, you have four SDK-version-tracking surfaces if you go SDK. With raw REST you have one OpenAPI spec, four thin HTTP clients, and uniform behaviour across all four codebases. The OpenAPI spec becomes the source of truth, and SDK drift across languages stops being a problem you have to think about.
Low-frequency calls. If you’re calling the emissions API a few hundred times a month from a backend service, the SDK’s convenience isn’t saving you meaningful engineering time. A 30-line HTTP client wrapped in your service’s logging conventions does the job. The SDK’s value scales with call volume; at low volume, it’s a dependency you carry for no gain.
The questions to ask any emissions vendor
Beyond the SDK-vs-API choice, here is the actual vendor-evaluation checklist I run when our customers are comparing emissions providers. These are the questions whose answers separate the rigorous vendors from the marketing-led ones.
1. What is the emission factor table refresh cadence?
GLEC v3.2 was published in 2023. ISO 14083:2023 was published the same year. Factor updates between major releases (the v3.x sub-revisions) come out every 6–18 months. A vendor that says "we use GLEC" without specifying which version and which sub-revision is one whose factor table is probably stale. Ask: what is the publication date of your current production factor table? When do you plan to upgrade to v4 when it drops? How long is the lag between an upstream methodology revision and your production rollout?
Good answer: "We pin to GLEC v3.2 as of the March 2026 errata sheet; v3.0 and v3.1 are available as named historical methodologies for restatement; we run an internal review on each upstream change with a 30–60 day rollout target." Suspicious answer: "We use GLEC."
2. What is your audit trail durability?
For CSRD assurance and CDP submission, the auditor will ask: "show me the specific factor and version your system used for this specific shipment on this specific date." A vendor whose responses don’t include the methodology version, the factor reference, and the calculation timestamp in machine-readable form is one whose data won’t survive audit. Ask: what fields are in your API response? Is the methodology version pinned per response? How long do you retain calculation_id-level records? Can I retrieve historical calculations by ID?
Good answer: every response includes methodology_version, factor_source, calculation_timestamp, and a stable calculation_id; calculations are retained for at least 7 years; historical retrieval is supported. Suspicious answer: "We don’t expose those fields, but we can confirm we use GLEC."
3. What is your retry policy?
API calls fail. Networks blip. Rate limits hit. A credible vendor has a documented retry policy with exponential backoff suggestions, idempotency support, and clearly defined HTTP status code semantics. Ask: which response codes are retryable? Do you support idempotency keys to prevent double-calculation? What is your rate limit (ours is a monthly quota per plan — pricing), and what happens at the limit (HTTP 429 vs queue vs hard reject)? How do you signal transient vs permanent failure?
Good answer: idempotency keys supported via Idempotency-Key header, 429 with Retry-After header, 5xx are retryable with exponential backoff, 4xx are non-retryable by design. Suspicious answer: "Just call us back if it fails."
4. What is your idempotency model?
When a customer integration retries a failed request, you do not want a second calculation to be recorded against the customer’s usage quota or to produce a different result. The standard pattern is an Idempotency-Key header that returns the same calculation_id and the same response on retry within a 24-hour window. Stripe popularised this pattern; emissions vendors that take audit trail seriously should support it. Ask: do you support idempotency keys? What is the deduplication window? What happens if the same key is sent with different payloads?
Good answer: yes, 24-hour deduplication window, conflicting payloads return 409. Suspicious answer: "You can use request_id for that." (No — request_id is the server’s assigned tracking number, not a client-controlled deduplication key.)
5. Is your calculation deterministic, given the same input?
For a CSRD restatement or an audit replay, the auditor may ask: "if I send the same shipment payload through your API today and tomorrow, do I get the same number?" The answer should be yes, with one explicit caveat: factor table updates legitimately change the result. The vendor should expose a way to call against a pinned methodology version so that replay against historical data is possible. Ask: can I pin the methodology version per request? Will my historical calculations stay reproducible after you update factors?
Good answer: yes — methodology version is pinnable per request, historical calculations remain queryable by ID with the original methodology version, restatement is an explicit opt-in flow. Suspicious answer: "Our factors always reflect the latest methodology."
6. What happens when GLEC v4 or ISO 14083 revisions land?
GLEC v4 is in draft. ISO 14083 will have errata cycles. A vendor that hasn’t answered the migration question is one whose customers will get surprised. Ask: when GLEC v4 publishes, what is your rollout plan? Will my existing integrations break? How are you handling versioning?
Good answer: v4 enters as a separate selectable methodology, v3.2 stays available as a named historical methodology for restatement, no breaking changes to the API surface, customers opt in to v4 on their schedule. Suspicious answer: "We’ll handle it."
What I’d say to my counterpart at a different vendor
If I were buying emissions API services, not selling them, here is the order I would evaluate:
- Read the API documentation publicly available without signing up. If the docs require a sales call to access, walk away.
- Make a few raw HTTP calls from a Postman collection or curl. If you can’t get the API working in 10 minutes against a sandbox key, walk away.
- Check whether the response includes methodology version, factor source, and a calculation ID. If not, walk away.
- Test the retry behaviour by intentionally killing a request mid-flight and reissuing with the same idempotency key. Confirm you get the same calculation_id back, not a new one. If the vendor doesn’t support idempotency keys, walk away.
- Ask for the pricing publicly. If it’s "contact sales for pricing" with no published tier, the vendor is doing per-customer custom pricing and you’re paying the negotiating-power-asymmetry tax. Sometimes that’s fine, but know that it’s the deal you’re making.
- Read the SDK source code if available. Look for hard-coded retry logic, request batching behaviour, and error-mapping. The SDK quality is a proxy for the engineering quality of the underlying API.
The SDK can be in your stack or not. Either is fine. What matters is the underlying API, the audit trail, and the vendor’s seriousness about versioning and reproducibility. Those are the differentiators that survive the first audit cycle, not the marketing-page promises.
One scope caveat on the framework
The framework above assumes the integration target is a backend service or batch pipeline. For client-side use cases — embedding a freight emissions calculator inside a shipper checkout flow, for instance — the SDK story shifts. There you usually want a tiny client-side SDK because raw cross-origin REST calls have authentication and CORS complications, plus the SDK can handle widget initialization and styling. The EcoFreight embed pattern at /embeds uses an iframe rather than an SDK to avoid the cross-origin complications, but that’s a slightly different design choice.
For the comparative API integration patterns I’ve seen against other freight emissions vendors, see the API comparison post. The technical questions in this post apply to all the vendors in that comparison; how each one answers them is in that piece. For the ML-side emissions question — specifically when route optimisation actually moves emissions and when it’s noise — see the ML route optimisation write-up.
Closing
SDK or raw API is an engineering choice that depends on your integration pattern, your language stack, your dependency tolerance, and your migration risk appetite. There is no universally correct answer. There are vendor-pushed answers, and there are answers that survive five years of integration evolution. The vendor evaluation questions above — factor refresh cadence, audit trail durability, retry policy, idempotency model, determinism guarantees, versioning roadmap — are what separate the vendors you can build a long-running integration against from the ones you can’t. Use SDKs where they earn their weight, use raw REST where they don’t, and don’t let a marketing page choose for you. For a head-to-head against other vendors see our comparisons, or jump to Climatiq, Pledge, or Lune.
One honest gap I will name plainly
We do not yet ship first-party Python or Node SDKs. Q3 2026 is the internal target, with the OpenAPI spec at /docs as the only currently-supported integration surface. Webhook-driven push of recalculated results also is not supported — if GLEC Framework v3.2 revises a factor and we recompute your back-catalog, you find out by polling the calculation_id, not by receiving a push. Both are on the roadmap. Neither is in production. If either is a deal-breaker, BigMile (for bulk reconciliation) or Climatiq (for first-party SDKs) is probably the better near-term fit; see the vendor comparison post for the rest of the trade-offs.
Sources
Stripe Engineering, the idempotency primer at stripe.com/blog/idempotency. The OpenAPI specification (formerly Swagger) for API documentation standards — openapis.org. RFC 7231 and RFC 6585 for the HTTP status code semantics referenced above. The GLEC Framework v3.2 publication and ISO 14083:2023 for the methodology-versioning patterns this post leans on. Idempotency-key best practices drawn from IETF draft-ietf-httpapi-idempotency-key-header.