Key facts
| Endpoint | POST https://api.plugsky.com/v1/chat/completions |
| Mode | response_format: {"type":"json_object"} for guaranteed-valid JSON syntax |
| Schema mode | JSON-Schema-constrained structured outputs are supported on capable models |
| Prompt requirement | Include the word JSON in the prompt and show the expected shape |
| Determinism | seed and low temperature make repeated runs more stable |
| Failure handling | Validate every payload; repair with the validation error in a follow-up turn |
| Model support | Check the model card — capability varies across the 30+ model catalogue |
| Product status | Live |
TL;DR
- JSON mode guarantees parseable JSON; it does not guarantee the right fields.
- Describe the exact object in the prompt and mention JSON explicitly.
- Use a JSON Schema when the model supports it, enums and all.
- Validate with Pydantic or Zod, then repair — never trust semantics.
- Set temperature low and a seed when you need repeatable output.
How it works, step by step
- Define the target object, then write the prompt to request exactly that shape.
- Set response_format to json_object, or pass a JSON Schema if the model supports structured outputs.
- Mention JSON in the prompt and include a minimal example of the expected payload.
- Parse the response, then validate it with your schema library of choice.
- On validation failure, retry once with the validation error appended to the conversation.
- Log raw payloads and failure rates per model to catch drift after model changes.
- Keep temperature low and set a seed when downstream systems need stability.
Try it yourself
Open the function calling schema generator →
JSON mode versus structured outputs
Two levels of guarantee are available:
- JSON object mode (
{"type":"json_object"}) constrains the model to emit syntactically valid JSON. Great for extraction and classification; the field names are still up to the model. - JSON Schema mode passes a schema so the output conforms to your fields, enums and required list. Availability varies by model, so check the catalogue card before designing around it.
Both live on the same chat completions endpoint, so switching between them is one request field.
Prompting for the shape you want
JSON mode is a syntax constraint, not a specification. The prompt still carries the contract: name every field, describe its meaning, list allowed values, and show a compact example. For extraction tasks, include the source text and an explicit instruction to output only JSON. Put the schema in the system message and keep the example minimal — oversized examples invite copying rather than extraction.
resp = client.chat.completions.create(
model="plugsky-lite",
messages=[
{"role": "system", "content": "Extract fields as JSON: {\"name\": str, \"amount\": number, \"currency\": str}"},
{"role": "user", "content": invoice_text},
],
response_format={"type": "json_object"},
temperature=0,
)Validation and repair loops
Syntax-valid JSON can still be semantically wrong: negative quantities, invented enum values, missing fields or narrative text smuggled into a string. Validate with Pydantic in Python or Zod in TypeScript and treat failure as a first-class branch. One repair attempt is usually enough: append the validation error as a user message and ask for a corrected payload. Track repair rates per prompt and per model — a spike after a model upgrade is your earliest warning that extraction quality moved.
Where structured output fits
Use JSON mode for classification, entity extraction, form filling, report generation and any step that feeds code rather than a human. For multi-step pipelines, keep every hop structured — an extraction step that emits typed JSON is far easier to test than one that emits prose a parser guesses at. Pair it with function calling when the model must both decide and act: tools express the action, structured output expresses the data you store. JSON mode is live today across supported models; check /docs and /models for per-model capability before standardising a pipeline.
Honest comparison
| Capability | Plugsky JSON mode | Prompt-only JSON | Post-hoc parsing |
|---|---|---|---|
| Syntax guarantee | Valid JSON enforced | Best effort | None |
| Schema constraints | JSON Schema mode on capable models | Prompt description only | Reject and retry |
| Failure recovery | Repair turn with validation error | Manual retries | Parser exceptions |
| Determinism help | Low temperature plus seed | Temperature only | Not applicable |
| Observability | Token usage in every response | Same | Custom logging |
| Status | Live | Live but brittle | Fragile |
Frequently asked questions
Does JSON mode guarantee my schema?
No. JSON object mode guarantees syntactically valid JSON. Field-level guarantees require JSON-Schema structured outputs, and even then you should validate semantics such as ranges and business rules.
Which models support structured outputs?
Capability varies across the 30+ model catalogue. Check the model card on /models and test your schema against the exact model you plan to deploy.
Do I need to mention JSON in the prompt?
Yes. Include the word JSON in the prompt and show the expected shape, even when response_format is set. It measurably reduces empty or off-target payloads.
How do I make output repeatable?
Set temperature to 0 or close to it and pass a seed where the model supports one. Repeat runs become more stable, though not bit-identical across provider changes.
What should I do when validation fails?
Retry once with the validation error appended to the conversation, asking for a corrected payload. Track repair rates per model to catch regressions early.
Can I combine JSON mode with function calling?
Yes. Use tools for actions and structured output for data; they are independent request fields on the same endpoint.
Is there an extra charge for JSON mode?
No separate charge. Self-serve plans are flat monthly with fair-use usage; token counts are still returned in every response for observability.
Does JSON mode work with streaming?
Yes, but buffering the full response is simpler when you must parse a complete object. Stream when partial output is useful, and validate after the final chunk.