BuildRequest parameters

Request parameters

⚠️
Preview — this feature is being built; the design below is the spec.

Four settings shape almost every request: how long the reply may be, the instructions the model follows, where it must stop, and who the request is for. This page covers each one on POST /v1/chat/completions. The same fields exist on Messages with the names noted below.

Today only max_tokens and the system message reach the model; stop, user and metadata are accepted and ignored. This page is the design for honouring all of them.

At a glance

FieldTypeDefaultPurpose
max_tokensintegermodel’s max_output_tokensCap on output tokens.
messages[0] with role: "system"messagenoneInstructions for the whole conversation.
stopstring or array of up to 4 stringsnoneEnd the reply as soon as one of these strings is produced.
userstringnoneA stable id for the end user who triggered the request.
metadataobjectnoneYour own tags, stored with the usage record.

Endpoint and auth

POST https://app.syntic.ai/v1/chat/completions
Authorization: Bearer sk_live_...
Content-Type: application/json

max_tokens

The highest number of tokens the reply may contain. When generation reaches it, the reply ends and finish_reason is length.

  • Must be a positive integer no larger than the model’s max_output_tokens (see Models). Larger values return 400 max_tokens_too_large instead of being clipped.
  • Reasoning tokens count against it when reasoning is on.
  • It caps the reply only. Input size is limited separately by the model’s context window.
  • max_completion_tokens is accepted as an alias. Sending both with different values returns 400 conflicting_parameters.

System instructions

Put instructions in one system message at the start of messages. On the Messages endpoint use the top-level system field instead.

Syntic places a short identity instruction ahead of your text. Your instructions follow it unchanged and take priority for everything the identity instruction does not cover. A second system message later in the conversation is treated as a system note at that point, which is useful for switching mode mid-conversation.

stop

One string or a list of up to four. When the model produces any of them, generation ends before that string, and the string itself is not included in the reply.

RuleValue
Count1 to 4 strings
Length1 to 64 characters each
MatchingExact and case-sensitive, across token boundaries
Messages endpoint namestop_sequences (array only)

When a stop string ends the reply, the response says which one:

{
  "choices": [{
    "index": 0,
    "message": { "role": "assistant", "content": "Q1 revenue: 4.2M" },
    "finish_reason": "stop_sequence",
    "stop_sequence": "\n\n"
  }]
}

In a stream, the final chunk carries finish_reason: "stop_sequence" and stop_sequence. Text after the match is never sent, even in streaming mode, so a stop string can be relied on as a hard boundary.

user and metadata

user is a stable, opaque id for the person behind the request: a hashed account id, not an email address. Syntic uses it to trace abuse to one end user instead of blocking your whole key.

metadata holds your own tags. Syntic stores it with the usage record so you can filter usage reports by it.

KeyTypeNotes
end_user_idstringSame meaning as user. If both are sent they must match.
any other keystringUp to 16 keys, 64-character names, 512-character values.
⚠️

Do not put personal data such as names or email addresses in user or metadata. They are stored for as long as usage records are kept (see Data retention).

Neither field is sent to the model, and neither affects the reply.

Example

curl https://app.syntic.ai/v1/chat/completions \
  -H "Authorization: Bearer $SYNTIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Amara S1.2",
    "stream": false,
    "max_tokens": 200,
    "stop": ["\n\n", "END"],
    "user": "u_8f31c2",
    "metadata": { "feature": "invoice-summary", "tenant": "acme" },
    "messages": [
      { "role": "system", "content": "Summarise the invoice in one line. Write END when done." },
      { "role": "user", "content": "Invoice 4471: 12 x lavender 2L at 6.50, delivery 9.00." }
    ]
  }'

Errors

All errors use the unified envelope {error:{type, code, message, param}, request_id}.

StatuscodeparamCause
400max_tokens_too_largemax_tokensAbove the model’s output limit.
400invalid_typethe fieldWrong JSON type, for example max_tokens: "200".
400too_many_stop_sequencesstopMore than 4 strings.
400invalid_stop_sequencestop[i]Empty or longer than 64 characters.
400invalid_metadatametadata.<key>Too many keys, or a non-string or over-long value.
400conflicting_parametersthe second fieldmax_tokens and max_completion_tokens disagree, or user and metadata.end_user_id differ.

Build notes for the platform team

  • Forward stop in callUpstream(); if the upstream cannot stop on a string, cut the text server-side and still report stop_sequence.
  • In streaming mode hold back up to 63 characters at the tail so a partial match is never sent.
  • Store user and metadata on the usage row; index metadata.end_user_id.
Was this page helpful?