Back to API Design Best Practices
Q7Question 7 of 22

What is the difference between an API and an SDK

Key Concepts
  • The API is the language-neutral contract a service exposes: endpoints, request/response shapes, status codes, and authentication rules.
  • The SDK is a language-specific client library that wraps the API with typed methods, auth handling, retries, and serialization.
  • The SDK depends on the API; the API can exist without any SDK, but an SDK cannot exist without an API to wrap.
  • One API often has many SDKs, one per language (Java, Python, Go), all talking to the same contract.
  • SDKs speed up integration and reduce mistakes but add a dependency that must track API versioning.
  • In regulated banking, teams sometimes call the raw API directly for full auditable control over every byte sent.

Definition

The API is the language-neutral contract a service exposes; the SDK is a language-specific library that wraps that contract with auth, retries, serialization, and typed methods.
  • API (Application Programming Interface) – the contract a service exposes: endpoints, request/response schemas, status codes, headers, and authentication rules, independent of any programming language.
  • SDK (Software Development Kit) – a language-specific client library that wraps the API, providing typed methods, automatic auth handling, serialization/deserialization, retries with backoff, and error mapping.
  • Relationship – the SDK is built on top of the API; one API can have many SDKs (Java, Python, Go), all talking to the same contract.
  • Trade-off – SDKs speed integration but add a versioned dependency; calling the raw API gives maximum control.

The API is the official rulebook of National Bank of India: to transfer money, send a form of this exact shape to this counter, and you will get back a receipt of this shape. Anyone who can read the rulebook can transact, in any language. The SDK is a personal bank assistant who already knows the rulebook by heart. You say "transfer fifty thousand to Priya" and the assistant fills the correct form, stands in the right queue, retries if the counter is busy, and hands you back the receipt.

Understanding the Concepts

What is an API?

An API is the agreement a service exposes. For a REST service it is defined by the endpoints, the request body schema, the response schema, the HTTP status codes, the headers, and the authentication scheme. The API is often documented with OpenAPI/Swagger. Crucially, it says nothing about the client's programming language.

TEXT
POST /api/v1/transfers
Authorization: Bearer <token>
Content-Type: application/json

{ "from": "SAV2001", "to": "CUR3001", "amount": 50000 }

201 Created
{ "transferId": "TXF-001", "status": "COMPLETED" }

A caller in Java, Python, Go, or plain curl all interact with the same contract.

What is an SDK?

An SDK is a library in one language that hides the mechanics of talking to the API. Without an SDK, a developer must construct the URL, set headers, serialize JSON, send the HTTP call, check the status code, parse the response, handle timeouts, implement retries, and attach the auth token on every call.

JAVA
package com.bank.client;

import java.net.URI;
import java.net.http.*;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ManualApiCall {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        String body = mapper.writeValueAsString(
                new TransferRequest("SAV2001", "CUR3001", 50000));

        HttpRequest req = HttpRequest.newBuilder()
                .uri(URI.create("https://api.bank.com/api/v1/transfers"))
                .header("Authorization", "Bearer " + token)
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(body))
                .build();

        HttpResponse<String> resp = HttpClient.newHttpClient()
                .send(req, HttpResponse.BodyHandlers.ofString());
        // Must check status, parse JSON, handle errors, retry on 503...
    }
}

With an SDK, all that collapses to one typed method call.

JAVA
// With the SDK – one call, auth/retries/serialization handled:
import com.bank.sdk.BankClient;
import com.bank.sdk.model.TransferRequest;
import com.bank.sdk.model.TransferResult;
import java.math.BigDecimal;

BankClient client = BankClient.builder().apiKey(apiKey).build();
TransferResult result = client.transfers().create(
        new TransferRequest("SAV2001", "CUR3001", new BigDecimal("50000")));
System.out.println(result.transferId());  // TXF-001

What conveniences does an SDK provide?

An SDK typically handles authentication by storing and refreshing tokens automatically. It serializes request objects to JSON and deserializes responses back into typed objects. It maps HTTP errors to language-native exceptions. It implements retries with exponential backoff for transient failures. And it may expose pagination as an iterator.

JAVA
// SDK maps HTTP 404 to a typed exception:
try {
    client.accounts().getById("INVALID-999");
} catch (AccountNotFoundException e) {
    System.out.println(e.getMessage()); // "Account INVALID-999 not found"
}

// SDK paginates automatically:
for (Transaction txn : client.transactions().list("SAV2001")) {
    System.out.println(txn.amount()); // iterates through all pages
}

How do API and SDK relate? (comparison table)

| Aspect | API | SDK |
|---|---|---|
| Definition | Contract: endpoints, schemas, status codes | Library wrapping the contract |
| Language | Language-neutral | Language-specific |
| Dependency direction | Independent | Depends on the API |
| Client effort | Build URLs, serialize, handle errors | One typed method call |
| Versioning | API version (v1, v2) | SDK version tracks API version |
| Count | One per service | Many (Java, Python, Go, etc.) |

When should you use the raw API vs the SDK?

Use the SDK for fast integration, reduced boilerplate, and consistent error handling. Use the raw API when you need full auditable control over every byte, when the SDK does not exist for your language, or when the SDK lags behind the latest API features.

JAVA
// In regulated banking, calling the raw API gives full control:
// Every header, every retry, every byte is explicit and auditable.
HttpRequest req = HttpRequest.newBuilder()
        .uri(URI.create("https://api.bank.com/api/v1/transfers"))
        .header("X-Idempotency-Key", UUID.randomUUID().toString())
        .header("Authorization", "Bearer " + token)
        .POST(HttpRequest.BodyPublishers.ofString(body))
        .build();
// The audit log records exactly what was sent.

What are common mistakes?

A common mistake is using an outdated SDK version that does not match the API version, causing silent field mismatches. Another mistake is trusting the SDK's retry policy without understanding it: an SDK may retry a non-idempotent POST, duplicating a transfer.

JAVA
// Wrong – SDK retries a POST /transfers without an idempotency key:
client.transfers().create(request);  // if the SDK retries, duplicate transfer!

// Correct – always send an idempotency key for non-idempotent operations:
client.transfers().create(request, IdempotencyKey.of(UUID.randomUUID()));

How do you build an SDK for your API?

Tools like OpenAPI Generator read your API specification and generate client code in multiple languages. This ensures the SDK stays in sync with the API contract.

BASH
# Generate a Java SDK from the OpenAPI spec:
openapi-generator generate \
    -i api-spec.yaml \
    -g java \
    -o bank-sdk-java/ \
    --additional-properties=library=native,dateLibrary=java8

What should a senior engineer know?

For a public banking API, provide both the raw HTTP contract for maximum flexibility and official SDKs for convenience. SDK versioning must track API versioning: when the API adds a field, the SDK must be updated and a new version released. In a regulated environment, teams sometimes prefer calling the raw API so they have full, auditable control over every byte, rather than trusting an SDK's hidden retry or auth behavior. A mature API program publishes the OpenAPI spec, auto-generates SDKs, and tests them against the live API in CI.

Visual Overview

DIAGRAM
  API vs SDK:

  ┌─────────────────────────────────────────────────┐
  │                   API Contract                   │
  │  POST /api/v1/transfers                          │
  │  { from, to, amount } → { transferId, status }   │
  │  Status codes: 201, 400, 401, 404, 500           │
  └──────────────────┬──────────────────────────────┘
                     │
        ┌────────────┼────────────┐
        │            │            │
  ┌─────┴─────┐ ┌───┴─────┐ ┌───┴──────┐
  │ Java SDK  │ │Python SDK│ │  Go SDK  │
  │ .create() │ │.create() │ │.Create() │
  │ auth      │ │ auth     │ │ auth     │
  │ retries   │ │ retries  │ │ retries  │
  │ types     │ │ types    │ │ types    │
  └───────────┘ └─────────┘ └──────────┘

  Each SDK wraps the same API contract for its language.

Key Takeaway

An API is the contract a service exposes: the endpoints, request and response shapes, status codes, headers, and authentication scheme. It is language-neutral, so a client in Java, Python, Go, or plain curl all interact with exactly the same agreement, usually documented with OpenAPI. An SDK is a language-specific library that wraps that API and hides the mechanics: instead of hand-building URLs, attaching tokens, serializing JSON, and implementing retries, the developer calls a single typed method.

The SDK adds authentication handling that refreshes tokens automatically, serialization so you work with typed objects, error mapping so an HTTP 404 becomes a catchable exception, and resilience features like retries with exponential backoff. The relationship is one-directional: the SDK depends on the API, the API exists without any SDK, and one API commonly has many SDKs, one per language.

At National Bank of India, the team exposed a payments API to fintech partners and shipped a Java SDK. A partner integrating against the raw API had to write boilerplate for every call and kept making mistakes like forgetting token refresh. With the SDK they called one method and auth, JSON, retries with an idempotency key, and error mapping were all handled. Their Python and Go teams each got their own SDK wrapping the identical contract.

The trade-off to keep in mind is that an SDK speeds integration but adds a dependency to maintain, can lag behind the newest API features, and hides behavior like retry policy that you may need to tune. For a public API, provide both the raw contract and official SDKs. In highly regulated banking integrations, sometimes call the raw API directly for full auditable control.

Remember one sentence: the API is the rulebook everyone reads, and the SDK is the assistant who knows it by heart and fills out the forms for you.

---

Share
Use ← → arrow keys to navigate