# Your first LLM API request

## Start with the route contract

Use the [API key dashboard](/api-keys) to obtain a server-side key with access to your intended model. Keep it out of client bundles, screenshots and source control. Set `API_KEY` in your shell before running these examples. Discovery is read-only; generation requests incur usage.

```bash
curl --fail-with-body "https://newrouters.com/v1/models" \
  -H "Authorization: Bearer $API_KEY"
```

Use `/v1/models` to find an exact public model ID and its declared protocol and capabilities. This discovery response does not list supported endpoints. For this example, select a model with `protocol: "openai"`, then confirm in its current [model guide](/docs) that it supports `POST /v1/chat/completions`. The protocol label alone does not guarantee endpoint compatibility, and catalog visibility does not guarantee that your key can call the model. Check account access before continuing.

## Send a minimal request

Save this as `first-request.mjs` and set `MODEL_ID` to the verified public ID. This example uses Node.js built-in fetch and performs one request without automatic retries.

```javascript
const { API_KEY, MODEL_ID } = process.env;
if (!API_KEY || !MODEL_ID) throw new Error('Set API_KEY and MODEL_ID');
const response = await fetch('https://newrouters.com/v1/chat/completions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: MODEL_ID,
    messages: [{ role: 'user', content: 'Explain HTTP in three short steps.' }],
    stream: false,
  }),
  signal: AbortSignal.timeout(60000),
});
if (!response.ok) throw new Error(`Request failed: HTTP ${response.status}`);
const result = await response.json();
console.log(result.choices?.[0]?.message?.content ?? 'No text content returned');
console.log({ finishReason: result.choices?.[0]?.finish_reason, usage: result.usage });
```

Run `node first-request.mjs` on your server. Add an output limit only after checking which parameter the selected model accepts; token-limit and sampling parameters are not universal across models. The timeout is a client policy, not a server latency guarantee.

## Verify more than HTTP success

Inspect `finish_reason` before treating text as a complete answer. A length-limited response may need a smaller input or a reviewed output allowance. An empty text field may contain another response type or indicate a refusal; retain the native response for diagnosis without logging secrets or sensitive prompts.

LLM responses use the selected native protocol. They do not return the media `pending` task envelope and should not be polled through `/v1/tasks`. If the connection times out, do not assume generation was cancelled or free: investigate usage before resubmitting.

Continue with [protocol selection](/docs/llm/protocols), [errors and retries](/docs/llm/errors-and-retries), or the existing [GPT-6.1 Sol guide](/docs/models/gpt-6.1-sol). The model guide is an integration reference, not a guarantee of current availability.
