Skip to content

Types of APIs and Use Cases: Open, Internal, Partner

Core Concept LearningJuly 17, 20265 min readUpdated July 21, 2026

A travel checkout may call a public weather API, your own booking API, and a partner airline API. All three could use REST, but they should not share the same credentials, rate limits, or change policy. Choosing the audience boundary first makes the system easier to secure and evolve.

This guide separates who may call (Open, Internal, Partner) from how calls are shaped (REST, GraphQL, SOAP, gRPC). You will follow that travel request, see short code examples, and choose controls for each lane. For style depth, see REST vs GraphQL vs gRPC.

API classification uses two independent axes: audience and contract style
API classification uses two independent axes: audience and contract style

API types at a glance

Use two questions. Who may call? Open means outside developers under published terms; Internal means systems your organization owns; Partner means named companies under contract. How is the contract shaped? REST, GraphQL, SOAP, and gRPC answer that separate question.

One API can be Internal + REST. Another can be Partner + GraphQL. The travel flow below uses all three audience lanes, even though each call could use HTTP. Audience determines authentication, rate limits, SLAs, versioning pressure, and the cost of a breaking change.

Travel checkout crosses Open, Internal, and Partner API boundaries
Travel checkout crosses Open, Internal, and Partner API boundaries

Quick reference

  • Open — external developers; API key/OAuth; public docs; strict compatibility; abuse controls.
  • Internal — your services and product clients; workload/session identity; faster coordination; never trust the network alone.
  • Partner — named businesses; per-partner OAuth or mTLS; contract SLA; strict change window.
  • Style stays independent: REST/GraphQL often face clients; gRPC often connects services; SOAP survives where contracts require it.

Remember this

Audience (open/internal/partner) and style (REST/GraphQL/gRPC) are independent axes — the same travel request can cross all three lanes without changing its style.

Open APIs

An Open API (often called a public or developer API) is published for callers outside your employee network. Weather data, login with a third-party IdP, and product catalog fetch are classic cases. You still need keys, OAuth, quotas, and versioning — "open" means available under terms, not anonymous and unlimited.

REST dominates here: cacheable GETs, CDN edges, OpenAPI docs. GraphQL fits when many client apps need different field shapes from one product graph (feeds, custom dashboards). SOAP shows up when regulated industries still require XML envelopes and formal WSDL — bank transfers, insurance claims, government records — even when the marketing slide parks SOAP under "Open." Prefer REST/OpenAPI for greenfield public surfaces unless a partner mandate says otherwise.

Open API styles people actually publish
Open API styles people actually publish

Quick reference

  • Use cases: weather, public login/OIDC, product fetch, maps, payments SDKs.
  • REST — simple CRUD and CDN caching; default for public HTTP APIs.
  • GraphQL — mobile/web with divergent screens; watch query cost and depth.
  • SOAP — legacy and regulated XML contracts; do not choose it for fashion.
  • Ship OpenAPI (or a GraphQL schema) + rate limits before the first blog post.
Public REST product fetch
1// GET /v1/products/42 — cacheable, versioned2const res = await fetch("https://api.example.com/v1/products/42", {3  headers: { Authorization: `Bearer ${apiKey}` },4});5if (!res.ok) throw new Error(`product ${res.status}`);6const product = await res.json(); // { id, name, price }
Same need as GraphQL (shaped fields)
1// POST /graphql — client picks fields2const query = `query ($id: ID!) {3  product(id: $id) { id name price { amount currency } }4}`;5const res = await fetch("https://api.example.com/graphql", {6  method: "POST",7  headers: {8    "Content-Type": "application/json",9    Authorization: `Bearer ${apiKey}`,10  },11  body: JSON.stringify({ query, variables: { id: "42" } }),12});13if (!res.ok) throw new Error(`GraphQL HTTP ${res.status}`);14const payload = await res.json();15if (payload.errors) throw new Error(payload.errors[0].message);16const product = payload.data.product;

Remember this

An Open API's published contract and abuse controls are what an unknown caller relies on — REST vs GraphQL vs gRPC is a separate decision underneath that.

Internal APIs

Internal APIs connect systems you operate. Examples include payment sync between services, token checks between auth and checkout, stock updates, login requests, profile fetches, and live search. A browser may sit outside your network, but the product team still owns both sides of the contract.

A service-to-database call is usually not another API type. It is data access through a driver, ORM, or repository. Keep SQL behind the service that owns the table; otherwise every service becomes coupled to one shared schema.

Use REST or GraphQL for product clients and REST or gRPC between services. Authenticate internal callers with workload identity or mTLS. A private network is not proof that a caller should have access.

Internal: FE↔BE and service↔service — DB stays owned
Internal: FE↔BE and service↔service — DB stays owned

Quick reference

  • Backend→backend: payment sync, token verify, stock update.
  • Frontend→backend: login, profile, live search — still your contract.
  • Service→database: data access layer, not a peer of REST/GraphQL.
  • Internal ≠ insecure: rotate secrets, scope tokens, log callers.
Internal FE → BE (owned contract)
1// Browser → your BFF / API (same product boundary)2app.get("/api/me", requireSession, async (req, res) => {3  const profile = await profileService.get(req.userId);4  res.json({ id: profile.id, name: profile.displayName });5});
Not an "API type" — DB access stays behind a service
1// Wrong mental model: every service opens SQL to users table2// await pg.query("UPDATE users SET …")  // from cart, ads, CRM…3 4// Right: profile service owns the table; others call its API5await profileClient.patch(userId, { displayName });

Remember this

An Internal API is still an owned contract between teams — a raw DB driver connection isn't an API type at all, since nothing there is versioned or owned.

Partner APIs

Partner APIs sit between Open and Internal. A named counterparty — hotel chain, airline, payment gateway, affiliate network — calls you (or you call them) under a contract. B2B booking feeds, commission tracking, and health/finance/logistics data sharing belong here. Credentials are per-partner, often mutual TLS or OAuth client credentials with narrow scopes.

Change management is the real cost: partners cannot absorb weekly breaking changes. Version paths, publish deprecation windows, and measure partner-facing error budgets, not only your internal SLOs. Affiliate click analytics and product-link APIs look "simple" until dispute reconciliation needs immutable request IDs.

Partner lanes: B2B, affiliate, regulated data sharing
Partner lanes: B2B, affiliate, regulated data sharing

Quick reference

  • B2B: hotel booking, airline data, payment gateway.
  • Affiliate: product links, commission tracking, click analytics.
  • Data sharing: health, finance, logistics — often compliance-heavy.
  • Prefer contract tests and sandbox environments before production keys.
Partner-scoped call (sketch)
1// Airline inventory — partner client id + mTLS or signed JWT2const res = await fetch("https://partners.example.com/v2/flights/search", {3  method: "POST",4  headers: {5    "X-Partner-Id": partnerId,6    Authorization: `Bearer ${partnerToken}`,7    "Idempotency-Key": requestId,8  },9  body: JSON.stringify({ origin, destination, date }),10});11if (res.status === 429) throw new Error("Partner quota exceeded");12if (!res.ok) throw new Error(`Airline API ${res.status}`);13const flights = await res.json();
When Partner is the wrong label
1// Wrong: one shared "public" API key emailed to five vendors2// Right: per-partner credentials, scoped routes, contract tests3// Escalate to Open only when anonymous/developer-program traffic is the goal

Remember this

A Partner API needs per-counterparty auth, an SLA, and a negotiated change window — a shared public key and no notice period is how one partner's outage becomes everyone's outage.

Secure, version, document, and test

An API type is only the boundary. A usable API also needs an operating contract: authenticate callers, document requests and errors, test compatibility, monitor failures, and retire old versions without surprising clients.

The controls differ by audience. Open APIs need OAuth or scoped keys, rate limits, browser CORS rules, and stable public docs. Internal APIs need TLS plus workload identity or mTLS—not trust based on network location. Partner APIs need per-partner credentials, audit logs, sandboxes, and agreed deprecation windows. See REST authentication methods, JWT validation, and NGINX as an API gateway for implementation depth.

API lifecycle: design, secure, document, test, monitor, and retire
API lifecycle: design, secure, document, test, monitor, and retire

Quick reference

  • Version only when compatibility must break; prefer additive fields first.
  • Publish OpenAPI/GraphQL schemas and error examples, not endpoint names alone.
  • Test contracts in CI; give partners a sandbox before production access.
  • Monitor p95 latency, auth failures, rate-limit rejections, and deprecated-version traffic.
  • Rotate secrets and retire versions with a measured migration window.

Remember this

Each audience boundary raises the bar on a different control — open APIs need public docs and abuse limits, partner APIs need a retirement runway a single team can't unilaterally skip.

How to choose with evidence

Do not pick a branch by poster color. List caller classes for one product surface (browser, mobile, partner airline, public widget). For each class write: auth mechanism, expected QPS, PII exposure, and who pays when the contract breaks.

Promote Internal → Partner when a named company needs production access. Promote Partner → Open when you want a developer program and can staff abuse response. Pick REST vs GraphQL vs SOAP from the style comparison only after the audience lane is clear — style will not fix a wrong trust boundary.

Decide audience first, then style
Decide audience first, then style

Quick reference

  • Start Internal for the product you fully own.
  • Add Partner when legal + support can name the counterparty.
  • Add Open when docs, keys, and rate limits are funded.
  • Track: auth failures, partner tickets, p95, and breaking-change count per quarter.
  • If "Service to Database" appears on an architecture slide, redraw it as ownership + API.

Remember this

Defend an audience-lane choice with caller class, auth model, and change cost — a decision tree only illustrates the reasoning, it isn't the reasoning.

Key takeaway

Before choosing REST, GraphQL, SOAP, or gRPC, decide who should have access. Audience defines the trust boundary; style defines the contract. Separating those decisions produces APIs that are easier to secure, change, and operate. Keep database access behind the service that owns the data.

Practice (20 min): For the travel checkout, label five endpoints Open / Internal / Partner. Rewrite one service→database arrow as an owned service API. Then choose authentication and a version-retirement rule for the airline partner call.

Share:

Related Articles

Selecting the communication protocol between clients, API gateways, and internal microservices impacts API latency, payl

Read

Your mobile team wants one round trip for a screen. Your partner wants a stable URL they can cache. Your services need t

Read

Mobile users lose signal in elevators, on flights, and in rural areas, but they still expect edits to survive. An offlin

Read

Keep learning

Follow a structured path or browse all courses to go deeper.