Skip to content
ub3r.io

SDK Design · Chapter 1 · 11 min

Client shape and ergonomics

Namespaced resources, one config object and types that guide the happy path.

Resource-oriented architecture

The most successful SDKs are those that mirror the structure of the underlying API resources accurately. When a developer uses the ub3r library, they should be able to guess the method names based on the REST documentation they have already read. By grouping methods under resource namespaces like client.messages or client.webhooks, we provide a logical hierarchy that aids discovery through IDE autocomplete. This approach reduces the cognitive load required to switch between reading documentation and writing actual implementation code.

A single entry point for configuration is essential for maintaining a predictable and testable client state. Instead of scattered environment variable lookups, the ub3r client accepts a single options object containing credentials and global timeout settings. This design ensures that developers can explicitly control the client's behavior in multi-tenant environments where different keys might be needed. Providing sane defaults for these options allows for a quick start while still permitting deep customization for advanced production use cases.

Type-driven development

Using types as a primary interface design tool allows the compiler to catch errors before the code is even run. Discriminated unions for different message payloads ensure that only valid combinations of parameters are passed to the API. For example, an SMS payload should not allow media attachments, and the type system can enforce this restriction naturally. This leads to a "happy path" that is easy to follow and hard to break.

Namespacing prevents the client object from becoming a "God Object" with hundreds of flat methods. It allows for a clean separation of concerns where related actions are grouped logically under their respective domains. This structure mirrors the architectural boundaries of the service itself, making the SDK feel like a natural extension of the platform.

ts
const client = new Ub3r({ apiKey: "abc", timeout: 5000 });
const message = await client.messages.create({
  to: "+123456789",
  text: "Hello from the SDK",
  channel: "sms"
});

Response transparency

While methods should return parsed resource objects, they must also provide access to the raw HTTP response. Metadata such as request IDs and rate limit headers are vital for debugging production issues and monitoring usage. An SDK that hides this information forces developers to use hacks to extract critical system data. This transparency builds trust with senior engineers who need to understand exactly what is happening over the wire.

Every network call must be asynchronous and return a promise to avoid blocking the main execution thread. The ub3r SDK adopts modern async/await patterns to provide a smooth developer experience in both Node.js and browser environments. Consistent error handling within these promises ensures that failures are handled gracefully across different runtime contexts without crashing the application.

Discussion (3)

DO
Daniela Ortiz · 2026-10-04

The distinction between 'sent' and 'delivered' finally clicked for me here. We had dashboards treating them as the same thing for a year.

ue
ub3r editors · 2026-10-12

Good point — we're adding a short section on this in the next revision.

ML
Marcus Lindqvist · 2026-10-05

Would love a follow-up on how this behaves under carrier throttling. We see very different numbers per route.