---
slug: 53-llm-api-direct
title: Provider API directly
description: When you need full control, call the provider's HTTP API yourself with http_post + secret/bearer — gated by net(host), credentials never exposed.
example_ids: [llm-api-direct]
---

# Provider API directly

The built-in ops (`reason`/`decide`/…) cover most needs and keep you vendor-neutral. But when you need a parameter the ops don't expose (streaming, vision, a specific endpoint, your own retry logic), call the provider's HTTP API **yourself**. It's a normal HTTP request — so it's gated by `net(host)` and uses a `secret` for auth (see **[Secrets](/en/0.6.x/21-secrets)**).

```synsema
-- Doc example: calling a provider's HTTP API directly (instead of the built-in ops).
-- It's a normal HTTP request, so it is gated by net(host) and uses secret/bearer for auth.
intent: "doc example: provider API directly"
require net("api.anthropic.com")
require secret("ANTHROPIC_API_KEY")

task call_undeclared_provider()
    -- api.openai.com is NOT declared → the request is denied at the capability check
    give http_post("https://api.openai.com/v1/chat/completions", {}, {"x-api-key": secret("ANTHROPIC_API_KEY")})

test "a direct provider call is gated by net(host) like any HTTP request"
    assert_error(call_undeclared_provider)
```

## Anthropic (Messages API) — header is `x-api-key`, not Bearer

```synsema
require net("api.anthropic.com")
require secret("ANTHROPIC_API_KEY")

let r be http_post("https://api.anthropic.com/v1/messages",
    {"model": "claude-sonnet-4-6", "max_tokens": 256,
     "messages": [{"role": "user", "content": "Say hi"}]},
    {"x-api-key": secret("ANTHROPIC_API_KEY"),        -- raw secret in a CUSTOM header
     "anthropic-version": "2023-06-01"})
let text be (((json of r)["content"])[0])["text"]
```

## OpenAI / DeepSeek — `Authorization: Bearer`

```synsema
require net("api.openai.com")
require secret("OPENAI_API_KEY")

let r be http_post("https://api.openai.com/v1/chat/completions",
    {"model": "gpt-4o", "messages": [{"role": "user", "content": "Say hi"}]},
    {"Authorization": bearer(secret("OPENAI_API_KEY"))})
```

The key is a `secret`: it materializes only at the socket and is redacted in logs/errors. **When to use this vs. the built-in ops:** the ops for portability and validated decisions; the direct API for provider-specific features. You give up vendor-neutrality and the automatic context/validation.
