Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.phrony.com/llms.txt

Use this file to discover all available pages before exploring further.

Workspace files are shared with the file library in the Phrony dashboard. From the API you upload bytes out of band to object storage, then finalize the object so the runtime can resolve it for your agent runs. Requirements: The same X-API-Key must be used for presign, finalize, and run calls. The key must have Allow file uploads enabled. Otherwise POST to these routes returns 403. Paths are under /v1/file-library (relative to your API base URL).

The presign response

After a successful POST to Presign, you get storage coordinates and a time-limited upload target:
{
  "objectKey": "tenant/…/file.pdf",
  "uploadUrl": "https://…",
  "httpMethod": "PUT",
  "requiredHeaders": { "Content-Type": "application/pdf" },
  "expiresInSeconds": 3600
}

POST /v1/file-library/presign

Request a time-limited URL and required headers to upload a file to workspace storage (before finalize).
Request body (JSON):
FieldTypeRequiredDescription
filenamestringYes1–512 characters.
mediaTypestringYesContent type; unsafe or disallowed types are rejected for typical document and media flows.
maxContentLengthintegerYesMaximum upload size in bytes (positive; within platform limits). Must be the actual file size you will upload.
Response (success, JSON):
FieldTypeDescription
objectKeystringStorage key; use in finalize and when building file references.
uploadUrlstring (URL)Issue PUT to this URL with the file bytes.
httpMethod"PUT"Always PUT for the upload step.
requiredHeadersobjectHeader name → value. Send every header on the PUT (for example Content-Type and encryption-related headers).
expiresInSecondsintegerPresigned URL lifetime.

Upload bytes

Issue an HTTP PUT to uploadUrl with the exact requiredHeaders from the presign response. For browser or typical fetch uploads, do not rely on a fixed Content-Length baked into the signed URL; the uploader should set length from the file.

POST /v1/file-library/finalize

Confirm the uploaded bytes so the runtime can resolve the object for your agent. Idempotent for the same key.
Request body (JSON):
FieldTypeRequiredDescription
objectKeystringYesValue from presign after a successful PUT.
maxContentLengthintegerYesSame value as in presign; must be the actual uploaded size.
filenamestringNoDisplay name in the library; should match presign when possible.
mediaTypestringNoContent type label; should match presign when possible.
Response (success, JSON):
FieldTypeDescription
objectKeystringConfirmed storage key (same as in the request when successful).
sizeBytesstringStored size as a decimal string.
alreadyFinalizedbooleantrue if this key was already finalized (idempotent retry).

Use in a run

After finalize, pass a file reference in POST /v1/agents/{agentId}/runs body under input. Use the leaf file name (the segment after the last / in objectKey, for example a UUID name with extension), not a full path. phronyFile object in input (field name is up to your agent schema, e.g. document):
FieldTypeRequiredDescription
phronyFiletrueYesMust be the literal true.
filenamestringYesLeaf name only (same as the last segment of objectKey), not a full path.
mediaTypestringYesContent type of the uploaded file.
Example:
{
  "input": {
    "document": {
      "phronyFile": true,
      "filename": "a1b2c3d4-e5f6-7890-abcd-ef1234567890.pdf",
      "mediaType": "application/pdf"
    }
  }
}
For POST /v1/runs/{runId}/messages (or …/input), attach finalized files with the files[] shape in Runs API — Send input or messages (phronyFile, objectKey, optional filename / mediaType).

Examples (cURL, TypeScript, Python)

The PUT to uploadUrl must send every key/value in requiredHeaders from the presign response. Size maxContentLength must be at least the real byte size of the file.

Full flow: presign, upload, finalize, start a run

# Requires: jq, curl, file "document.pdf" in the current directory. Set AGENT_ID and API key.
export PHRONY_API_BASE="${PHRONY_API_BASE:-https://api.phrony.com}"
export PHRONY_API_KEY="phk_..."
export AGENT_ID="00000000-0000-0000-0000-000000000000"
FILE="document.pdf"
SIZE=$(wc -c < "$FILE" | tr -d ' ')

# 1) Presign
PRESIGN=$(curl -sS -X POST "${PHRONY_API_BASE}/v1/file-library/presign" \
  -H "Content-Type: application/json" -H "X-API-Key: ${PHRONY_API_KEY}" \
  -d "$(jq -n --arg f "$FILE" --arg m "application/pdf" --argjson c "$SIZE" \
      '{filename:$f, mediaType:$m, maxContentLength:($c|tonumber)}')")
echo "$PRESIGN" | jq .
OBJ=$(echo "$PRESIGN" | jq -r .objectKey)
UP=$(echo "$PRESIGN" | jq -r .uploadUrl)
LEAF=$(echo "$OBJ" | awk -F/ '{print $NF}')

# 2) PUT: one -H for each requiredHeaders entry
HARGS=()
while IFS= read -r line; do
  HARGS+=(-H "$line")
done < <(echo "$PRESIGN" | jq -r '.requiredHeaders | to_entries[] | "\(.key): \(.value)"')
curl -sS -X PUT "$UP" "${HARGS[@]}" --data-binary "@${FILE}"

# 3) Finalize
MAX=$SIZE
curl -sS -X POST "${PHRONY_API_BASE}/v1/file-library/finalize" \
  -H "Content-Type: application/json" -H "X-API-Key: ${PHRONY_API_KEY}" \
  -d "$(jq -n --arg o "$OBJ" --argjson c "$MAX" --arg f "$FILE" --arg m "application/pdf" \
      '{objectKey:$o, maxContentLength:($c|tonumber), filename:$f, mediaType:$m}')"

# 4) Start run (match input field names to your agent)
curl -sS -X POST "${PHRONY_API_BASE}/v1/agents/${AGENT_ID}/runs" \
  -H "Content-Type: application/json" -H "X-API-Key: ${PHRONY_API_KEY}" \
  -d "$(jq -n --arg f "$LEAF" --arg m "application/pdf" \
    '{input:{document:{phronyFile:true, filename:$f, mediaType:$m}}}')"
Adjust the input.document (or your real field name) to match the Input contract of your deployed agent version.