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
NONCE

Endpoints

API keys are created from Account settings. Analysis usage is charged to the owning account quota.

POST/api/agent/analysesanalysis:writeStart one analysis
GET/api/agent/analyses/:idanalysis:readPoll one analysis
POST/api/agent/analysis-batchesbatch:writeStart up to 10 analyses
GET/api/agent/analysis-batches/:idbatch:readPoll a batch
GET/api/agent/analysis-batches/:id/export?format=ideas-jsonexport:readExport pSEO JSON

Signing

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 owner
analysis:readPoll single-run status and URLs
batch:writeCreate bounded batches up to 10 ideas
batch:readPoll batch status and child run URLs
export:readExport completed batch items for pSEO

Responses

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 dispatch
PROCESSINGThe existing Preuve deep analysis pipeline is running
COMPLETEDThe dashboard URL is ready, and share URL is ready when publish is true
FAILEDThe run reached a terminal error with a stable code

reportUrl

/app/results?id=<reportId>

Private owner dashboard

shareUrl

/share/<shareId>

Public shared dashboard

ideas-json

ValidatedIdea[]

Batch export for pSEO