← Blog

LLM API Integration: A Practical Developer's Guide

2026-09-04 · 6 min read · SubToAPI Team

What "LLM API Integration" Actually Means

LLM API integration is the process of wiring a large language model into your application's backend so it can send prompts, receive completions, and handle the surrounding plumbing — authentication, streaming, error handling, rate limits, and observability. It's not just "call an endpoint and print the response." A production-ready integration needs to survive network failures, handle long-running streams, track token usage, and stay maintainable as your product grows.

If you're evaluating how to do this for the first time, the short answer is: pick an API-compatible provider, authenticate with a bearer token, send structured messages (system prompt + conversation history), and design your backend to handle both streaming and non-streaming responses. The rest of this article walks through each piece with working examples.

The Core Request/Response Loop

Every LLM API integration, regardless of provider, follows the same basic shape:

  1. Build a request with a system prompt, conversation history, and generation parameters (max tokens, temperature).
  2. Send it as an authenticated HTTPS POST.
  3. Parse the response — either a single JSON payload or a stream of server-sent events.
  4. Handle errors, retries, and rate limits.
  5. Log usage (tokens in/out, latency, cost) for monitoring.

A minimal non-streaming call looks like this:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4",
    "max_tokens": 1024,
    "messages": [
      {"role": "user", "content": "Summarize this ticket in one sentence."}
    ]
  }'

That single request already touches four integration concerns: authentication (the bearer token), payload structure (messages array), model selection, and response parsing. Get the plumbing right once and every feature you build on top — chat, summarization, agents — reuses the same foundation.

Authentication and Key Management

Most LLM APIs use a bearer token in the Authorization header. The integration mistake teams make most often is hardcoding keys into client-side code or committing them to version control. Keep keys server-side, rotate them per environment (dev/staging/prod), and scope them per application where possible.

If you're building on top of a Claude subscription rather than a raw provider API, tools like SubToAPI turn that access into standard sub_live_... application keys you can issue per app or per environment, with usage tracked centrally in a dashboard instead of scattered across scripts. See /docs/quickstart for the exact setup steps.

Streaming: Don't Bolt It On Later

Non-streaming responses are simpler to integrate but produce a noticeably worse user experience for anything conversational — users wait for the entire completion before seeing a single word. Streaming sends the response incrementally as server-sent events, which lets you render tokens as they arrive.

const response = await fetch("https://api.subtoapi.app/v1/messages", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "claude-sonnet-4",
    max_tokens: 1024,
    stream: true,
    messages: [{ role: "user", content: "Draft a release note for v2.3." }],
  }),
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  process.stdout.write(decoder.decode(value));
}

The architectural decision to make early is whether streaming flows all the way to your frontend or terminates at your backend. Streaming end-to-end (backend to browser via SSE or WebSocket) gives the best UX but adds complexity in connection handling, reconnects, and proxy timeouts. Buffering server-side and returning a complete response is simpler but slower to first byte. Full details on event formats are in /docs/streaming.

Tool Use and Structured Output

Many real integrations aren't just "chat" — they need the model to call functions: look up a record, run a calculation, query an API. This is done by declaring tools (name, description, JSON schema for inputs) in the request and handling the model's tool-call response by executing the function and returning the result in a follow-up message.

{
  "model": "claude-sonnet-4",
  "max_tokens": 1024,
  "tools": [
    {
      "name": "get_order_status",
      "description": "Look up the status of a customer order by ID",
      "input_schema": {
        "type": "object",
        "properties": {
          "order_id": { "type": "string" }
        },
        "required": ["order_id"]
      }
    }
  ],
  "messages": [
    { "role": "user", "content": "Where is order 48213?" }
  ]
}

The integration loop for tool use is: send request → model returns a tool call instead of text → your backend executes the tool → you send the result back as a new message → model produces a final answer. This round-trip is the backbone of most agentic features. See /docs/tools for the full schema and multi-turn examples.

Error Handling and Rate Limits

LLM APIs fail in predictable ways: rate limit errors (429), overloaded model errors (529/503), context length exceeded, and malformed requests. A resilient integration:

Don't retry blindly. A 400 error means your request is malformed — retrying it wastes time and money without changing the outcome.

Monitoring Usage and Cost

Token usage is the main cost driver, and it's easy to lose visibility once multiple services or team members are calling the API independently. Track input/output tokens per request, tag them by feature or endpoint, and set alerts on unusual spikes. Full docs for reading usage metadata off every response are at /docs/messages.

If you're consolidating access across a team — multiple developers, multiple apps, one Claude subscription — a dashboard that shows per-key usage avoids the spreadsheet-tracking problem entirely. SubToAPI issues separate API keys per application with usage broken down per key, which is useful once more than one project shares the same underlying access. Plans start at €9/month for solo use, with team and scale tiers for shared seats — see /pricing.

A Practical Integration Checklist

Start with the smallest working loop — one endpoint, one model, no streaming — then add streaming, tools, and monitoring incrementally. Trying to build all of it at once is where most integration projects stall.

Questions

Do I need a different integration for streaming vs non-streaming? No — same endpoint, same request body, just set stream: true and parse server-sent events instead of a single JSON payload. Design your backend to handle both from the start so you're not refactoring later.

How do I test an LLM API integration without burning through tokens? Use short max_tokens limits, cheap/fast models for development, and mock responses for unit tests. Reserve real API calls for integration tests and manual QA.

Can I integrate an LLM API without managing raw provider keys myself? Yes — services like SubToAPI sit between your app and your Claude access, giving you standard bearer-token API keys per application with usage tracking, so you integrate against one consistent API instead of managing raw credentials across projects. See /docs to get started.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →