Most backend engineers reach for raw HTTP first. It's the path of least resistance: fetch() or axios is already in your project, the API docs show curl examples, and you don't want to take a dependency on an SDK you haven't evaluated. This is reasonable. It's also a decision with a cost that compounds over time.
This isn't an argument that typed SDKs are always the right choice. They're not. For a one-off script that calls an API endpoint twice and discards the result, raw HTTP is fine. For production integrations that run continuously, handle pagination, manage auth token lifecycle, and are maintained by a team, the calculus is different.
The Raw HTTP Approach
Raw HTTP gives you maximum flexibility. You're dealing with Response objects, JSON parsing, and header manipulation directly. There's no abstraction between you and the wire. When something goes wrong, the debugging surface is narrow: you can inspect the exact request and response without any indirection layer.
The cost appears gradually. Your first endpoint is clean. Then you add auth token refresh because the token expired. Then you add a pagination loop because the response is paginated. Then you add retry logic because the API returns 429s under load. By the time you add idempotency key generation to avoid duplicate writes, you have four hundred lines of infrastructure code surrounding twenty lines of business logic. The infrastructure is untested, undocumented, and specific to this one connector.
Where Type Safety Matters for API Integrations
TypeScript generics on an SDK method give you more than autocomplete. They give you a compile-time contract: if the API response shape changes, your code fails at build time instead of at 3am in production when a field that your downstream code assumes is a string is now a number.
Consider what happens when an enterprise API silently renames a field — order_id becomes orderId. With raw HTTP and any typed response parsing, this change is invisible until the code that consumes the field throws a runtime error. With a typed SDK, the type for the connector's response shape is versioned and the mismatch surfaces as a type error when you update the SDK version.
This matters particularly for enterprise APIs that have slow, infrequent release cycles. Schema drift in ERP connectors is common: field renames, added required parameters, deprecated enum values that still exist in old records but aren't accepted in new writes. Type-safe response normalization at the SDK layer catches these at the earliest possible moment.
Response Normalization Across Connectors
The most useful thing a typed SDK does for multi-connector integrations is normalize response shapes. Without an SDK, a Contact record from Fieldvault CRM and a Customer record from Orbis ERP have different field names, different date formats, different ID formats, and different nesting. Your application code either deals with all of this directly — which means branching logic everywhere — or you write a mapping layer per connector.
A typed SDK can expose normalized TypeScript interfaces that downstream code depends on, independent of the connector-specific field names. The connector layer handles the mapping; your application code depends only on the normalized type. Add a new connector and the downstream code doesn't change.
Maintenance Overhead
The often-overlooked cost of raw HTTP integrations is maintenance when the upstream API changes. API versioning is inconsistent across enterprise vendors. Some version with URL prefixes (/v2/contacts), some with headers (Accept: application/vnd.api+json;version=2), some don't version at all and simply change responses with a changelog entry. When the API changes, raw HTTP integrations require you to find and update every call site.
With a typed SDK, the connector layer is updated once. If the field rename is handled at the connector level, your application code's TypeScript types don't change and your downstream code compiles without modification.
The SDK approach is not free — you're trading flexibility for abstraction, and abstractions leak. When you need to send a request that the SDK doesn't expose, or when the SDK's behavior diverges from what you need, you're fighting the abstraction. This is a real cost. The question is whether the abstraction handles the common 90% of cases correctly and provides an escape hatch for the 10% that are genuinely connector-specific. Devloom's client.raw() method is that escape hatch.
When to Use Each
Use raw HTTP when you're writing a one-off script, when you need full control over every aspect of the request, or when you're evaluating an API before committing to an integration. Use a typed SDK when you're building a production integration that will run continuously, handle multiple connectors, or be maintained by a team. The boilerplate that raw HTTP requires you to write — auth management, pagination, retry — is correctness-critical infrastructure that benefits from being solved once in a well-tested library rather than rediscovered per integration.