When you integrate LLM endpoints, you usually start from a curl snippet in the provider docs. Building a repeatable curl to postman collection llm api workflow turns those one-off commands into shared, variable-driven requests your team can run, test, and extend. This is a concrete entry in the cURL LLM API Cookbook: we take real commands, import them, and harden them into a collection that survives spec changes.
Step 1: Gather representative curl commands
Pull the exact commands you need from the LLM provider or gateway docs. Focus on the endpoints you will actually call: chat completions, embeddings, and maybe token counting. Do not generalize prematurely.
A minimal chat completion call looks like this:
curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role":"user","content":"Say hi"}],
"temperature": 0.7
}'
An embeddings call is just as important for retrieval pipelines:
curl https://api.openai.com/v1/embeddings \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"text-embedding-3-small","input":"hello world"}'
If you hit a gateway such as n4n.ai, the request shape is identical because it exposes an OpenAI-compatible endpoint. You only swap the base URL and the model string to address any of 240+ models behind that one route. Keep the original curl in a curl.md file so you can diff later when the provider changes a field.
Step 2: Import the curl into Postman
Postman parses curl directly. Open Import → Raw text, paste the command, and let the importer build the request. For the chat example, you get a POST with two headers and a raw JSON body.
The imported request is editable JSON. A cleaned-up version with variables looks like:
{
"name": "Chat Completion",
"request": {
"method": "POST",
"header": [
{"key": "Authorization", "value": "Bearer {{api_key}}"},
{"key": "Content-Type", "value": "application/json"}
],
"body": {
"mode": "raw",
"raw": "{\"model\":\"{{model}}\",\"messages\":[{\"role\":\"user\",\"content\":\"{{prompt}}\"}]}"
},
"url": "{{base_url}}/v1/chat/completions"
}
}
The curl to postman collection llm api import is lossless for simple requests, but watch for shell variable expansion. If your curl used $OPENAI_API_KEY, Postman imports the literal string, not the secret. Fix that in the next step. For the embeddings call, repeat the import; Postman creates a second item you can rename.
Step 3: Externalize configuration with environment variables
Create a Postman environment (or a collection variable set) with these keys:
base_url:https://api.openai.com(or your gateway URL)api_key: your secret keymodel:gpt-4o-miniprompt: default test stringembed_model:text-embedding-3-small
Reference them with {{var}} syntax. This decouples the request definition from deployment targets. You can maintain one collection and run it against staging, prod, or a local mock by switching environments.
An environment file exported from Postman looks like:
{
"name": "LLM Local",
"values": [
{"key": "base_url", "value": "https://api.openai.com", "enabled": true},
{"key": "api_key", "value": "sk-...", "enabled": true, "type": "secret"},
{"key": "model", "value": "gpt-4o-mini", "enabled": true}
]
}
For a gateway that honors client routing directives, you might add a router_model variable and pass it in the body or a header. The point is to keep the request template static.
Step 4: Handle authentication securely
Never hardcode keys in the collection JSON you commit to Git. Use Postman’s secret type for api_key or store it in a local environment that is git-ignored.
If your provider supports fine-grained scopes, create a key with only chat.completions access. For OpenAI-compatible gateways, the Authorization: Bearer header is sufficient. Some gateways forward provider cache-control hints; you can add headers like Cache-Control: max-age=3600 if the upstream supports prompt caching.
A robust curl to postman collection llm api setup isolates secrets and uses the same auth pattern across all requests via a collection-level pre-request script:
pm.request.headers.add({
key: "Authorization",
value: `Bearer ${pm.environment.get("api_key")}`
});
This removes the need to set the header on every item. If you rotate keys, change one environment field, not ten requests.
Step 5: Parameterize the request body
LLM requests are rarely static. Drive the body from variables and pre-request scripts. Replace the hardcoded message with a variable and optionally load a longer prompt from a file.
In the body tab, switch to raw + JSON and use:
{
"model": "{{model}}",
"messages": [{"role": "user", "content": "{{prompt}}"}],
"temperature": {{temperature}},
"max_tokens": {{max_tokens}}
}
Define temperature (e.g., 0.7) and max_tokens (512) as collection variables. For batch testing, use a pre-request script to iterate prompts:
const prompts = ["Summarize this", "Translate to French", "Code a quicksort"];
pm.variables.set("prompt", prompts[Math.floor(Math.random() * prompts.length)]);
This turns a single curl example into a fuzzable request. For embeddings, set input from a {{embed_input}} variable so you can test batch sizes.
Step 6: Add tests to verify responses
Postman tests run after the response arrives. For LLM endpoints, assert transport success and structural integrity. A minimal test block:
pm.test("status is 200", () => pm.response.to.have.status(200));
pm.test("response has choices", () => {
const json = pm.response.json();
pm.expect(json.choices).to.be.an("array").with.length.greaterThan(0);
pm.expect(json.choices[0].message.content).to.be.a("string");
});
pm.test("usage is metered", () => {
const json = pm.response.json();
pm.expect(json.usage).to.have.property("total_tokens");
});
Your curl to postman collection llm api tests should also catch malformed streaming responses if you use stream: true. In that case, disable the JSON parse test and check for text/event-stream content type.
If you use a gateway with per-token usage metering, the usage object is authoritative. Assert it matches your expected magnitude to detect silent truncation. For embeddings, assert data[0].embedding.length equals the model’s dimension (e.g., 1536).
Step 7: Chain requests for multi-turn flows
Real agents call the model multiple times. Use Postman’s pm.collectionVariables to pass state.
After a completion, store the assistant message:
const json = pm.response.json();
pm.collectionVariables.set("last_reply", json.choices[0].message.content);
The next request can embed {{last_reply}} in a follow-up user message. This mirrors how you would build a conversation loop in code and validates that your prompt templating works before you write a line of Python. You can also chain embeddings → search → chat by saving an embedding vector and injecting it into a system prompt via a pre-request script.
Step 8: Export and version control
Postman collections are JSON. Export as Collection v2.1 and commit to your repo under postman/. Keep environments separate and uncommitted if they hold secrets.
A good convention:
postman/
llm-api-collection.json
README.md
env/
local.postman_environment.json (git-ignored)
Run postman collection run in CI with Newman to block regressions:
newman run postman/llm-api-collection.json -e env/local.postman_environment.json
Newman exits non-zero on test failure, which makes it a cheap smoke test for your LLM integration before a deploy.
Common pitfalls when building a curl to postman collection llm api
Shell variables in curl do not survive import—always replace them with {{vars}}. Trailing slashes on base_url cause double-slash URLs; pick one convention. Model names are case-sensitive and drift between providers; centralize them in variables. JSON body escaping in the raw editor is strict—use the Pretty formatter to avoid stray quotes. Finally, if you test against a gateway with automatic fallback when a provider is degraded, do not assert a specific upstream latency; assert only response shape.
Verifying success
Success means the collection runs end-to-end with zero manual edits. Open Postman, select your environment, hit Runner, and execute the collection. All tests should pass: 200 status, non-empty choices, and a usage block present.
If you are on a gateway that provides automatic fallback when a provider is rate-limited or degraded, simulate a 429 on one upstream and confirm the request still returns a valid completion from the fallback. That validates both your collection and your routing config.
Finally, share the collection with a teammate who has never seen the curl. If they can run it and get a sane response in under two minutes, the curl to postman collection llm api conversion earned its place in your cookbook.