Any HTTP client
Tracira works with any tool that can make an HTTP POST request, including Zapier, Pipedream, custom scripts, or your own server.
Tracira works with any tool that can make an HTTP POST request: Zapier, Pipedream, custom scripts, or your own server. Here is the complete request format.
Get your webhook token
Open the Integrations tab in your workspace and copy your token from there.
Send the request
POST to https://tracira.com/api/logs with:
- Header:
Authorization: Bearer YOUR_TOKEN - Body: JSON with at minimum
projectandoutput
Use the verdict
Pass "sync": true to receive the evaluation result immediately in the response.
Check status: pass means all rules passed, flagged means at least one rule
triggered.
Send an output
curl -X POST https://tracira.com/api/logs \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project": "my-project",
"output": "The AI-generated text.",
"sync": true
}'Response
{
"ok": true,
"id": "b1c2d3e4-...",
"status": "pass"
}Logging a conversation
For a chatbot or any multi-turn thread, send one output per exchange and group the
turns with sessionId - don't send the full messages array on every call:
{
"project": "Customer Support",
"input": "Hi, my order #8841 never arrived. Can you help?",
"output": "Sorry to hear that! I've checked order #8841 and...",
"sessionId": "thread_5f2a"
}inputis only the newest user message - the one this reply answers. Your call to your AI provider can still carry the full history; Tracira only needs the new turn.sessionIdis your conversation or thread ID, identical on every turn. Tracira stitches all outputs sharing it into one readable thread, nothing repeated. (conversationId,threadId, andchatIdare accepted as aliases.)- Leave the system prompt out - it's configuration, not conversation. The best place for it is Tracira itself - see Hosted instructions.
Hosted instructions (self-improving prompts)
Tracira can host the instructions (system prompt) your AI runs with, versioned, with the people who review its output able to read, edit, and restore them in the dashboard. Fetch them at the start of every run instead of hardcoding the prompt:
curl -X POST https://tracira.com/api/instructions \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project": "Customer Support",
"task": "Email reply",
"default": "You write friendly, concise replies to customer emails..."
}'
# -> { "content": "You write friendly...", "version": 3, "updatedAt": "..." }The very first call saves default as version 1 and returns it; after that, the stored
text always wins and default is ignored. Use content as your system message, and
include the version when you submit the output so it links back to the exact
instructions that produced it:
{
"project": "Customer Support",
"task": "Email reply",
"input": "Where is my order?",
"output": "It ships tomorrow...",
"instructionsVersion": 3
}To make the prompt self-improving, react to a changed decision: rewrite the current
instructions with your own AI step so the reviewer's comment is followed from now on,
then save the result as the new active version:
curl -X POST https://tracira.com/api/instructions/versions \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project": "Customer Support",
"task": "Email reply",
"content": "You write friendly, concise replies... Always sign off as The Support Team.",
"teachComment": "Always sign off as The Support Team",
"logId": "b1c2d3e4-..."
}'
# -> { "version": 4 }Tracira stores, versions, and serves the text - the rewriting stays in your automation, with your own AI step and keys. See the API reference for the full schemas.
Reviewers can also coach replies that already went out: pressing Teach the AI on a
decided or passed output fires a taught webhook event. It carries the same fields as a
changed decision (comment, output, instructionsVersion, ...) but nothing should
be regenerated or resent - route it to the same instructions-rewrite step so the lesson
applies from the next run onward.
Reviewing an action before it runs
When your AI decides to do something with side effects (issue a refund, delete a record, send an escalation), you can hold that action for human approval. Two fields do two different jobs, and you usually want both:
actiondescribes what is being reviewed. Tracira shows reviewers the plain-languagesummaryso they know exactly what they are approving.requireApprovaldecides whether a person is asked at all. Set it totrueand the output waits in the review queue no matter what your rules conclude.
{
"project": "Customer Support",
"output": "I have prepared the refund and sent it for approval.",
"action": {
"name": "issue_refund",
"summary": "Refund €49.00 to Alice Martin (order #8841)",
"params": { "amount": 49.0, "currency": "EUR", "order": "8841" }
},
"requireApproval": true,
"callbackUrl": "https://hook.eu1.make.com/abc123"
}An action on its own does not stop anything
action is a description, not a gate. Send it without requireApproval and your
rules alone decide: in a workspace with no rule that matches this project and task,
the output passes and your automation runs the refund unreviewed. If a person must
sign off, say so with requireApproval.
Your automation supplies the summary - write it as a clear sentence, because
reviewers read it verbatim to decide. Tracira never executes the action itself.
Rules still run either way, and they are the right tool when only some actions need
a person: a data-field rule on action.params.amount flags refunds over a threshold
and lets smaller ones through. When a rule flags the output, its explanation is what
the reviewer reads; requireApproval only adds the reviewer, it never overwrites what
your rules found. Nothing else about your payload changes - both fields are optional
and additive.
Attaching files
Tracira can store images, audio, and PDFs alongside an output so reviewers see the source the AI worked from. How you attach depends on the file size. For a file Tracira already holds, see Getting a file back out instead: re-attach it by key rather than sending the bytes a second time.
The 4.5 MB request-body limit
The /api/logs request body is capped at 4.5 MB by our hosting platform. Because
base64 inflates a file by about 33%, a base64-inline file effectively has to stay under
~3 MB. Larger files return 413 FUNCTION_PAYLOAD_TOO_LARGE. For anything bigger, use a
URL or a presigned upload (below), where the file never travels in the request body.
Small files: URL or inline base64
{
"project": "Invoice Review",
"output": "...",
"attachments": [
{ "source": "url", "url": "https://example.com/invoice.pdf" }
]
}source: "url" (Tracira fetches it server-side, up to 32 MB) or source: "upload" with
base64 data (kept under the 4.5 MB body cap).
Large files: direct upload (up to 32 MB)
Upload the file straight to Tracira's storage, then reference it by key. Three calls:
Create the upload
curl -X POST https://tracira.com/api/uploads \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "filename": "invoice.pdf" }'
# -> { "uploadUrl": "https://...", "key": "...", "contentType": "application/pdf" }Upload the bytes
PUT the raw file to uploadUrl with the Content-Type from the response. These bytes go
straight to storage, not through /api/logs, so they are not subject to the 4.5 MB cap:
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: application/pdf" \
--data-binary @invoice.pdfSubmit the output
Reference the upload by key. Nothing else is needed; Tracira links the file to this output:
curl -X POST https://tracira.com/api/logs \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project": "Invoice Review",
"output": "The invoice looks valid.",
"attachments": [{ "source": "uploaded", "key": "KEY_FROM_STEP_1" }]
}'Quota and cleanup
Each in-flight upload reserves space against your workspace storage quota (the sizeBytes
you declare, or the per-file max if omitted), so pending uploads can never push you over
your plan limit. The reservation is released when the upload is linked to an output, and any
upload never referenced by an output is deleted automatically within 24h. Linked files count
toward storage like any other attachment.
Tip
For Zapier or Pipedream: use their built-in HTTP/Webhook action, set Method to POST,
add the Authorization header, and paste the JSON body. Then add a conditional step
after it to branch on status. For files over ~3 MB, do the create-upload + PUT as two
HTTP steps before the final POST.
Getting a file back out
Every payload that describes an output carries an attachments array: the webhook events,
the per-output callbackUrl, and GET /api/logs/{id}. Each entry names one stored file:
"attachments": [
{
"role": "input",
"type": "file",
"filename": "invoice-april.pdf",
"contentType": "application/pdf",
"key": "WORKSPACE_ID/LOG_ID/0-ab12cd34-invoice-april.pdf",
"url": "https://tracira.com/api/media/WORKSPACE_ID/LOG_ID/0-ab12cd34-invoice-april.pdf"
}
]role is input when the AI received the file and output when it produced one. key and
url name the same object; use whichever your tool maps more easily.
This is what makes a redo possible for document work. When a reviewer sends a parsed PDF back with a comment, your automation has long since finished and no longer holds the file. Ask Tracira for it instead.
Download the file
Exchange the key or URL for a short-lived signed link, then fetch it:
curl -G https://tracira.com/api/media-url \
-H "Authorization: Bearer YOUR_TOKEN" \
--data-urlencode "source=WORKSPACE_ID/LOG_ID/0-ab12cd34-invoice-april.pdf"
# -> { "url": "https://...", "expiresAt": "...", "key": "...", "filename": "...", "contentType": "..." }
curl "$SIGNED_URL" -o invoice-april.pdfDo not send your token to the signed URL
The signed link carries its own signature in the query string and rejects any request that
also carries an Authorization header. Most HTTP clients reuse headers across calls, so
send the token to /api/media-url only.
The same trap applies to GET /api/media/{key}, which redirects to that signed link: a
client that follows redirects will carry your header along and get a 403 from storage. Use
/api/media-url for automations and save the redirect route for browsers.
Keep the file on the new version
When you resubmit the corrected output, re-attach the same file by key instead of uploading it again:
curl -X POST https://tracira.com/api/logs \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project": "Invoice Review",
"output": "{\"total\": 1245.00}",
"revisionOf": "LOG_ID",
"attachments": [{ "source": "stored", "key": "WORKSPACE_ID/LOG_ID/0-ab12cd34-invoice-april.pdf" }]
}'The url works here too: paste it in place of the key and Tracira reads the key out of it.
Each version keeps its own copy
A re-attached file is copied into the new output rather than shared with the old one. That is deliberate: deleting an output deletes its files, so a shared file would vanish from the revision the moment someone cleaned up the original. It does mean a document revised three times is stored four times and counts four times toward your storage quota.
If the original output has already been deleted or has passed your activity history limit,
the re-attach fails with a 422 saying the file is no longer stored. Send the file itself
in that case.