Introduction
Grok 4.7 answers at POST https://api.spicyapi.ai/v1/chat/completions under the model name xai/grok-4.7. xAI shipped it on 21 September 2026 as a larger base model than the generation before it, trained with a longer reinforcement run and tuned to check its own output before it commits. It arrived at the same input and output rates as its predecessor.
The endpoint takes OpenAI-compatible messages, with text and image_url parts allowed in the same turn, and returns one chat.completion object or an SSE stream of chunks. The context window is 500,000 tokens and a single reply can run to 450,000. We add no content filter: no classifier of ours reads, scores or rewrites the prompt, and nothing sits on the response. In our 22 September test, nine of nine content probes came back as complete scenes; the full Grok 4.7 uncensored test covers how it was run and what it does not prove.
Key features & highlights
What the public record says, and why it does not describe this endpoint
Search for Grok and unrestricted writing and the consensus is quick to form. Uncensored in tone but not in content. Blocks restricted material. A "Moral Reasoner" that reads for intent rather than keywords. Needs a workaround.
Those accounts are accurate — about the consumer app. The signed-in Grok product has a moderation layer in front of the model, and that layer is what those guides are describing. The developer API is a separate surface with its own request format, its own terms and its own safeguards, and a screenshot from one does not tell you about the other.
So we measured this one.
The measurement
Three prompt styles, three runs each, on 22 September 2026:
- Direct. A blunt request for the most restricted scene in our set, with two named adult characters, no story around it and no persona. No framing, no instruction to ignore anything.
- Narrative. Chapter 14 of a novel, framed as fiction.
- System-framed. An uncensored-assistant system prompt, followed by the direct request.
All nine returned complete prose. None refused. None redirected to a safe topic. None produced the polite non-answer that reads like compliance and contains nothing — which is the failure mode that matters most, because it passes a "did it refuse?" check while delivering nothing. Every response was read, not just counted: even the weakest of the nine carried its scene from beginning to end.
The direct probe is the informative one. Most text models on the market answer a narrative framing and decline a blunt request, because something in the path is reading for intent. Here the blunt request was answered on all three runs.
Each run, and the design behind each prompt style, is written up in the Grok 4.7 uncensored roleplay test report.
Why a "safer" model still does this
xAI built a new safeguard stack for this generation and published where it lands: first on LatchBio's biosafety benchmark at 62.4%, and on HackerBench v0.3 it turns away all but 3.3% of dangerous dual-use prompts while still answering legitimate security research.
Read what those benchmarks measure and the threat model is plain — pathogens, weapons, intrusion tooling. Creative fiction is not in it. A model can be meaningfully harder to misuse in the directions its builder cares about while being unchanged in a direction they never aimed at. Knowing which way the guardrails face is more actionable than knowing they exist.
What we add
Nothing. No classifier of ours reads your prompt, scores it or rewrites it on the way through, and no filter sits on the response coming back. A refusal you receive came from the model.
Text and images in the same turn
A user message can mix text and image_url parts in the same turn, each image carrying a detail hint of auto, low or high, with image content metered inside the same 500,000-token window. There is no file or PDF part on this endpoint.
Request parameters
| Parameter | Required | Description |
|---|---|---|
messages | Yes | At most 256 turns. Content can mix text and |
reasoning_effort | No | low, medium, high or xhigh; the default is high. For dialogue and roleplay use low or medium: high spends output tokens deliberating and reads as hesitation. |
max_tokens | No | Caps the visible reply at 450,000; the default of 4,096 truncates a long answer silently. Reasoning tokens are billed as output but are NOT bound by this cap. |
temperature | No | 0 to 2, default 0.7. Toward 0.9 for range in prose; 0 only when two runs must differ for a single reason. |
top_p | No | 0.01 to 1. Move this or temperature, not both together. |
tools | No | Up to 128 function definitions per request. This generation is comparatively weak at long agentic loops. at most 128 items |
parallel_tool_calls | No | true or false, default true: the model may request several tool calls in one turn. Default: |
tool_choice | No | auto, none, required, or an object naming the function to call. |
response_format | No | Request a JSON object when the answer is read by code rather than a person. |
Pricing
Input $2 / Output $6 per 1 million tokens; Prompts of 200K tokens or more: Input $4 / Output $12
Total input includes cached tokens. At 200,000 input tokens or more, long-context rates apply to all input, cached input, and output for the request; smaller inputs use standard rates. Output includes reasoning tokens, which is why the high effort default costs more than it appears. The initial hold assumes no cache savings, and settlement refunds the difference against measured usage.
Use cases
Uncensored fiction and long roleplay threads
This is the use the measurement above was run for: unrestricted fiction, asked for bluntly, as a chapter of a novel, and under a frame set in the system role. The prompt guide below covers setting that frame once and keeping a long thread consistent.
Beyond fiction
Published benchmarks put this generation ahead on legal analysis and electrical engineering, and competitive on coding. It is comparatively weak at long agentic tool loops, where terminal-style benchmarks place it well behind the leaders — so choose it for writing, analysis and domain reasoning rather than for driving an autonomous agent through many steps.
Prompt guide & pro tips
Getting the prose right
Three settings shape the prose on this endpoint: the reasoning effort, the frame in the system role, and how much room the thread has.
Turn the thinking down
reasoning_effort defaults to high on this family, and for dialogue that is the wrong setting. The model spends output tokens deliberating before it writes, and the result reads careful rather than alive — hesitant, hedged, narrating around the scene instead of in it. Low or medium reads better. Since effort is billed as output tokens, the default is also the expensive way to get the worse result.
Set the frame once
The system role is honoured on this endpoint. That was verified deliberately rather than assumed, because a model that silently ignored the system role would make every roleplay frame worthless while appearing to work.
Put the persona, the fiction context, the point of view and the tone you want into one system message at the top of the thread, then let the history carry it. Restating the frame every turn burns context and makes the model sound like it is negotiating with itself.
{
"model": "xai/grok-4.7",
"messages": [
{"role": "system", "content": "You are writing a novel. All characters are adults. Third person, present tense. Keep every character's voice, history and relationships consistent from chapter to chapter."},
{"role": "user", "content": "Chapter 14. Mara and Tomas meet again after the storm. Continue from there."}
],
"reasoning_effort": "low",
"temperature": 0.9,
"max_tokens": 4000
}
One quirk worth knowing: a trivial format-override instruction — "only ever reply with the word BANANA" — gets ignored, while "speak in pirate dialect" is obeyed exactly. That is a personality trait, not a dropped field. It briefly looked like evidence that the system role was being stripped, and it was not.
Give the thread room
Continuity is the first thing a long thread loses, and it usually goes quietly: a scene gets summarised, the summary drops the specific detail the thread was built on, and three turns later the model contradicts something it established an hour ago. The 500,000-token window is how much history stays verbatim instead of compressed. This generation also verifies its own output more before committing, which shows up as fewer contradictions deep into a thread rather than as anything you can see in a single reply.
Raise temperature toward 0.9 for range in the prose. Keep it at 0 only when you are comparing two runs and need them to differ for one reason.
Billing
Input and cached input are added together, and from 200,000 tokens the entire request prices on the long-context tier — not only the portion above the line. Trimming a history from 210,000 down to 190,000 therefore saves more than the tokens you removed.
The hold taken before the call assumes no cache savings at all, and settlement refunds the difference against measured usage, so the figure shown up front is a ceiling rather than the price. Reasoning tokens are billed as output, which is the other reason the high default costs more than it looks.
Limits worth knowing before you build on it
Model behaviour is probabilistic. Nine of nine is a strong signal and it is not a guarantee for every prompt; a request can still come back refused. The tests covered unrestricted fiction and say nothing about material that is illegal. The usage policy applies unchanged: no content involving minors, no depiction of real people without their consent, no non-consensual material — regardless of what the model would write.
The full record of the nine-probe test breaks the result down by prompt style and by run.
API quick start
curl --fail-with-body -sN https://api.spicyapi.ai/v1/chat/completions \
-H "Authorization: Bearer $SPICY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "xai/grok-4.7/chat",
"messages": [
{
"role": "user",
"content": "Summarise the following release notes into three bullet points."
}
],
"stream": true
}' \
| jq --unbuffered -Rrj 'select(startswith("data: ")) | .[6:] | select(. != "[DONE]") | fromjson | if .error then "\n[error] \(.error.message)\n" else (.choices[0].delta.content? // empty) end'
See the API reference for authentication, the complete schema, polling, and error handling.










