Skip to content

Sending a text

POST /v1/prisms/{prism}/results

One call answers one text. {prism} is the prism's slug or id, and the body is JSON:

Key Type Required What it does
fields object This or text One string per field of the prism version, keyed by field key.
text string This or fields Shorthand for a prism whose only field is text.
ref string No Your reference for the text, returned with the result. 1 to 200 characters.
version integer No The prism version to answer with. The latest saved version by default.
idempotency_key string No Makes the call safe to repeat. 1 to 200 characters.

Send Content-Type: application/json. Every key is snake_case, and the API ignores keys it doesn't know, so a misspelled idempotencyKey does nothing and raises no error.

fields must hold exactly the field keys of the prism version, no more and no fewer. Every value is a string. Send an empty string for a field you have nothing for.

{
"fields": {
"subject": "Charged twice this month",
"text": "Hi, I was billed twice for September. Please refund the second charge before Friday."
}
}

A missing or extra key answers 400 and nothing is saved:

You send message
fields without subject Missing fields: subject
fields with an extra body Unknown fields: body
A number instead of a string Invalid request: fields.subject: Expected string, received number

A prism whose only field is text also takes the text on its own:

{ "text": "Hi, I was billed twice for September. Please refund the second charge before Friday." }

The API turns it into {"fields": {"text": "..."}}. Send one of fields and text. Both, or neither, answers 400 with Invalid request: fields: send either fields or text. support-routing has two fields, so {"text": "..."} answers 400 with Missing fields: subject.

Put your own id for the text in the reference, ref, such as a ticket number. It comes back in the response and in every CSV, TSV and JSON Lines row, so you can match results to your records. It does not have to be unique. Leading and trailing spaces are trimmed.

A prism's context is the same for every call. When part of the background changes per call, such as each client's billing guideline or refund policy, send it as context:

{
"text": "Conf with J. Smith re strategy, 1.5h",
"context": "Acme Corp guideline: no charges for internal conferences between firm lawyers."
}

The model reads the prism's context, then a line Context for this call:, then yours. Say in the prism's context or questions which one wins when they disagree, for example "Where the context for this call conflicts with the rules above, it wins."

  • It is optional. An empty or blank value is the same as leaving it out.
  • It counts toward the size of the call. See Size limits.
  • It is saved with the result and shown on the result's page in the app. The API does not return it, and no row or download holds it.
  • A repeated idempotency_key returns the stored result, whatever context the repeat sends. A retry sends the stored context again.

A call runs the latest saved version of the prism. The response's version tells you which one answered.

When someone saves a new version in the app, the next call runs it. That is what you want for a question rewrite. It breaks your integration when the new version adds or removes a field, because your code still sends the old keys. Pin the version to keep the field set steady until your code catches up:

{
"version": 3,
"fields": {
"subject": "Charged twice this month",
"text": "Hi, I was billed twice for September. Please refund the second charge before Friday."
}
}

A pinned call sends the field keys of that version. A version that does not exist answers 404 with Prism version not found. The Lens is not part of a version, so a pinned call still gets the prism's current Lens in json.

With an idempotency_key, repeating the call returns the stored result instead of answering the text again. Use a key derived from your record, such as tck-8812-1, and send it on every call you might repeat. Errors and retries has the rules, including how unique a key must be.

  • Each field value is at most 100,000 characters, enough for a whole call transcript. A longer one answers 400 with Invalid request: fields.text: String must contain at most 100000 character(s).
  • The fields, the prism's context, the call's context and the longest question must fit in about 26,000 tokens together. Prismlet counts four characters of their JSON as one token, which comes to about 104,000 characters, and the more context and question text the prism has, the less room is left for the fields. Over the budget, the call answers 400 with Request too large: about 27100 tokens of fields, context and the longest question, the limit is 26000. Prismlet's estimate is four characters per token, and text that is not English, or has many numbers or symbols, uses more real tokens, so a call close to the budget can still be refused by the model provider and come back as a failed result.
  • context is at most 100,000 characters. A longer one answers 400 with Invalid request: context: String must contain at most 100000 character(s).
  • The whole body is at most 1 MiB. A larger body answers 413.

Nothing is saved and nothing reaches the model when a call fails one of these checks. Limits lists every limit in one table.

The call waits for the answers. Each attempt to reach the model has 15 seconds by default. A 429 or a 5xx from the model gets one more attempt. A timeout, a network error or any other error from the model fails the call at once. So a call can take about 30 seconds before it fails. Set your client timeout above that. The examples in these docs use 45 seconds.

curl --max-time 45 ...

A call that runs out of time on the model's side is saved as a failed result and answers 502.