Skip to main content
POST
Finish a stopped or failed upload from its stored copy

Authorizations

Authorization
string
header
required

Your API key, shaped sp_<key_id>_<secret>, sent as Authorization: Bearer sp_.... It identifies your organization, not a person. Your organization owns the agents, holds the credit, and is billed. Every key your organization holds reaches the same things, so you rotate a key by minting the new one, deploying it, and revoking the old one.

Keep the key on your server. A request that carries a Sec-Fetch-Site header is refused with 400, because only a browser sets that header. Priors sends no CORS headers, so a browser blocks the call before it leaves the page. The secret is shown once when the key is minted and is stored only as a hash. A lost secret is replaced, never recovered.

An administrator of your organization mints and revokes keys in the Priors application, under Settings. There is no endpoint for it: a key reaches your whole organization, so issuing one is an act of administration.

Headers

X-SP-End-User
string

Your own identifier for the person this request acts for: an account number, a row id, anything stable on your side. It works only with a partner API key. The value is not stored. Priors hashes it together with your organization id, so two clients that send the same string are still two different people.

With the header, you reach the threads that same person created and no others. A new thread is recorded against that person, and GET /v1/agents/{agent_id} returns that person's conversations only. Without the header, the key acts as the organization and reaches every thread on every agent it owns. Learned memory is shared across the agent either way. Only the thread list narrows.

Sent with anything that is not a partner API key, the header returns 400 instead of being ignored. Sent empty or as whitespace, it also returns 400, and it is never read as absent: absent means the whole organization, which is wider access than you asked for. Surrounding whitespace is removed. The 255-character limit is measured on the value as sent.

Required string length: 1 - 255
Pattern: \S

Path Parameters

agent_id
string
required

Unique managed memory-agent identifier.

Maximum string length: 32
Pattern: ^agent_[0-9A-HJKMNP-TV-Z]{26}$
thread_id
string
required

Unique thread identifier scoped to the agent.

Maximum string length: 33
Pattern: ^thread_[0-9A-HJKMNP-TV-Z]{26}$
source_id
string
required

The stored document.

Pattern: ^src_[0-9a-f]{32}$

Body

application/json
here
boolean
default:false

Read the whole file again in this thread, instead of finishing it in the thread where it was uploaded. This stores a second copy, charged in full.

max_chars
integer

The splitting settings the upload was sent with, as on observe-file (this field and the two below). Priors normally remembers them and ignores these. They matter only for an older upload whose settings were not recorded. A partial upload resumes only with the settings it was read with; other settings return 409.

Required range: 200 <= x <= 4000
overlap_chars
integer
Required range: x >= 0
strategy
enum<string>
Available options:
auto,
length,
sentence,
code,
structure

Response

Accepted. The body is the same as the observe-file response. Poll the job it names.

agent_id
string
required

Server-generated agent identifier.

Pattern: ^agent_[0-9A-HJKMNP-TV-Z]{26}$
thread_id
string
required

Server-generated thread identifier.

Pattern: ^thread_[0-9A-HJKMNP-TV-Z]{26}$
observation_id
string
required

Server-issued identifier for the asynchronous ingestion. Pass it to the observation status endpoint to follow progress.

Pattern: ^obs_[0-9A-HJKMNP-TV-Z]{26}$
accepted
boolean
required
turns_total
integer
required

How many turns the document was split into. Exact when deferred is false, because conversion and splitting happened in-request. 0 when deferred is true; the status endpoint reports the real count once conversion finishes.

filename
string
required

The uploaded filename, which also becomes each turn's speaker.

doc_format
string
required

The canonical document format actually converted, e.g. pdf.

source_id
string
required

Identifier of the persisted original. Empty when ingestion succeeded but source storage was unavailable.

deferred
boolean
default:false

True when the document needed OCR and had more pages than can be read inside one request. It was accepted and is being converted in the background; poll the status endpoint. A conversion failure is that job's error.

figures
integer

Figures kept from the document. Each is stored as a crop and described inline in the turn where it appeared; figures add no turns of their own.

figures_dropped
integer

Figures omitted because the document exceeded extraction budgets.

Required range: x >= 0
words_total
integer

Words across every turn the upload produced (text chunks plus figure captions). The input side of what this upload is billed — the same count /observe would bill for the same turns.

Required range: x >= 0
duplicate
boolean
default:false

True when this agent had already ingested a document with these exact bytes, so nothing was read, stored or billed for this request. observation_id, turns_total and source_id then describe the ORIGINAL ingest, not this call. Show it as "already processed" rather than as a fresh upload — claiming new work happened would be untrue, and the progress it reports is already finished.

document_state
enum<string>

Where this document stands for this agent. completed with duplicate: true is a reuse; ingesting with duplicate: true means a job was already running and this request joined it rather than starting a second, so its progress is worth polling. Absent on a plain first upload, which is simply in progress.

Available options:
ingesting,
partial,
completed,
failed
queued
boolean

True when the agent was reading another file. This file is accepted and waits its turn (the status field queued), then starts by itself. You do not need to send it again.