Agent API
Run analyses from your CLI, agent, or pSEO pipeline.
Create signed requests, poll report status, return the same dashboard URLs a human user sees, and export completed batches as structured JSON.
METHOD
PATH
QUERY
SHA256_RAW_BODY
TIMESTAMP
NONCEEndpoints
API keys are created from Account settings. Analysis usage is charged to the owning account quota.
/api/agent/analysesanalysis:writeStart one analysis/api/agent/analyses/:idanalysis:readPoll one analysis/api/agent/analysis-batchesbatch:writeStart up to 10 analyses/api/agent/analysis-batches/:idbatch:readPoll a batch/api/agent/analysis-batches/:id/export?format=ideas-jsonexport:readExport pSEO JSONSigning
Send x-preuve-key, x-preuve-timestamp, x-preuve-nonce, and x-preuve-signature. Nonces are single-use inside a five minute window.
body='{"clientRunId":"pseo-online-001","idea":"A workflow automation service for solo founders that validates market demand before they build.","publish":true}'
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
nonce=$(openssl rand -hex 16)
body_hash=$(printf "%s" "$body" | openssl dgst -sha256 -binary | xxd -p -c 256)
canonical="POST
/api/agent/analyses
$body_hash
$timestamp
$nonce"
signature="sha256=$(printf "%s" "$canonical" | openssl dgst -sha256 -hmac "$PREUVE_AGENT_SECRET" -binary | xxd -p -c 256)"
curl https://preuve.ai/api/agent/analyses \
-H "content-type: application/json" \
-H "x-preuve-key: $PREUVE_AGENT_KEY" \
-H "x-preuve-timestamp: $timestamp" \
-H "x-preuve-nonce: $nonce" \
-H "x-preuve-signature: $signature" \
--data "$body"Node client
Keep PREUVE_AGENT_SECRET server-side. The canonical query line is empty when the request has no query parameters.
import { createHash, createHmac, randomUUID } from 'node:crypto';
async function signedFetch(path, { method = 'GET', body } = {}) {
const rawBody = body ? JSON.stringify(body) : '';
const timestamp = new Date().toISOString();
const nonce = randomUUID();
const canonical = [
method,
path,
'',
createHash('sha256').update(rawBody).digest('hex'),
timestamp,
nonce,
].join('\n');
const signature = createHmac('sha256', process.env.PREUVE_AGENT_SECRET)
.update(canonical)
.digest('hex');
return fetch(`https://preuve.ai${path}`, {
method,
headers: {
'content-type': 'application/json',
'x-preuve-key': process.env.PREUVE_AGENT_KEY,
'x-preuve-timestamp': timestamp,
'x-preuve-nonce': nonce,
'x-preuve-signature': `sha256=${signature}`,
},
body: rawBody || undefined,
});
}Scopes
Scopes are exact. Write access for analyses does not grant export access.
analysis:writeCreate analysis runs for the key owneranalysis:readPoll single-run status and URLsbatch:writeCreate bounded batches up to 10 ideasbatch:readPoll batch status and child run URLsexport:readExport completed batch items for pSEOResponses
Polling returns status and URLs. Report data stays in the authenticated dashboard or public share view.
{
"id": "run_123",
"reportId": "report_123",
"clientRunId": "pseo-online-001",
"status": "PROCESSING",
"progressStep": "MARKET_RESEARCH",
"publish": true,
"reportUrl": "https://preuve.ai/app/results?id=report_123",
"shareUrl": "https://preuve.ai/share/abc123"
}Status lifecycle
Batches aggregate child runs into PROCESSING, COMPLETED, PARTIAL, or FAILED.
PENDINGThe run record exists and is waiting for dispatchPROCESSINGThe existing Preuve deep analysis pipeline is runningCOMPLETEDThe dashboard URL is ready, and share URL is ready when publish is trueFAILEDThe run reached a terminal error with a stable codereportUrl
/app/results?id=<reportId>Private owner dashboard
shareUrl
/share/<shareId>Public shared dashboard
ideas-json
ValidatedIdea[]Batch export for pSEO