---
title: "Start a client project"
method: POST
path: "/api/agent/agency/analyses"
tags: ["Agency"]
---

# Start a client project

`POST /api/agent/agency/analyses`

## Request

- Base URL: `https://preuve.ai`
- URL: `https://preuve.ai/api/agent/agency/analyses`
- Auth: API key in header `x-preuve-key`

Create one deep client report against the shared Agency project quota. Never falls back to personal credits. Async: 202 on a new dispatch, 200 with reused=true when the clientRunId replays an existing report. clientRunId is scoped to the calling key; reusing one that belongs to a different workspace is 409 CLIENT_RUN_ID_CONFLICT. A response carrying dispatchPending=true means the dispatch outcome is unknown - retry the same clientRunId and arguments after 60 seconds; recovery reuses the original report and credit. 503 TRIGGER_DISPATCH_FAILED is a definite rejection: the credit was restored and that request stays failed on replay, so a new attempt needs a new clientRunId. Creating a report here does not email the client or publish a share link.

## Request body

- CreateAgencyAnalysisRequest
  - `clientRunId` string, required: Idempotency key, scoped to the calling API key.
  - `idea` string, required
  - `targetMarket` string
  - `targetCountry` string
  - `stage` string
  - `budget` string
  - `language` string
  - `scanType` 'deep': Optional and deep-only. An Agency project always spends one shared deep project credit; any other value is 400 INVALID_SCAN_TYPE.
  - `publish` false: Not accepted here. Client share links are created in the Agency dashboard; publish=true is 400 INVALID_INPUT.

## Response `200`

Existing report replayed via clientRunId (reused=true).

- AgencyReportStatus
  - `reportId` string
  - `status` 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED'
  - `scanType` 'starter' | 'deep'
  - `analysisTier` string
  - `readyForExport` boolean
  - `reportUrl` string, uri
  - `createdAt` string, date-time
  - `pollAfterSeconds` integer: Present only while the report is not terminal.
  - `reused` boolean: Present when this clientRunId replayed an existing report.
  - `dispatchPending` boolean: The dispatch outcome is unknown. Retry the same clientRunId and arguments after 60 seconds; recovery reuses the original report and credit. Past 23 hours the recovery text directs you to support instead of risking a duplicate job.
  - `recovery` string: What to do next, present alongside dispatchPending.

## Other responses

- `202`: Client report created and dispatched.
- `400`: Invalid body (CLIENT_RUN_ID_REQUIRED, IDEA_TOO_SHORT, INVALID_SCAN_TYPE, INVALID_INPUT, INVALID_JSON).
- `401`: Missing x-preuve-key header (MISSING_API_KEY), or a malformed, unknown or revoked key (INVALID_AGENT_KEY - the same envelope for all three, on purpose). Repeated failures are throttled per IP and answer 429.
- `402`: The workspace has no payment method on file (PAYMENT_METHOD_REQUIRED). Deliberately not a 403: nothing is wrong with the key or the caller's permissions, and the fix is a billing action the owner takes in the Agency dashboard, after which the same clientRunId starts normally.
- `403`: Key does not carry agency:write (INSUFFICIENT_SCOPE), the member lacks scan permission in the workspace (AGENCY_PERMISSION_REQUIRED), no shared project credits (AGENCY_QUOTA_EXCEEDED), workspace pending approval (AGENCY_NOT_APPROVED), account suspended (ACCOUNT_SUSPENDED), or blocked address (IP_BLOCKED). Billing setup is NOT here - it answers 402, above. agency:write is not implied by analysis:write and did not exist before 2026-09-09, so a key created earlier always fails this check - see the AgencyInsufficientScope response for the recovery and the condition on each of its two routes.
- `404`: No Agency workspace on this account, or workspace membership was removed (AGENCY_NOT_FOUND). Membership is resolved live on every call.
- `409`: clientRunId belongs to another workspace (CLIENT_RUN_ID_CONFLICT) or the reservation is still settling (REQUEST_IN_PROGRESS - retry the same clientRunId).
- `413`: Body over the size limit (PAYLOAD_TOO_LARGE).
- `429`: Rate limited (RATE_LIMITED or DAILY_LIMIT_REACHED). RATE_LIMITED carries a Retry-After header with the seconds until the window resets; the quota-shaped codes clear on a different clock and put resetAt in the body instead.
- `500`: Unexpected server error (INTERNAL_ERROR, or TRIGGER_DISPATCH_FAILED when a deep scan could not be handed to the job runner). Never tell the user their quota is safe: on a deep scan the spend can already have happened when the failure hit, and an ambiguous dispatch deliberately keeps the report and its funding because the job may have been accepted before its response was lost. Treat consumption as unknown and retry with backoff. On an operation that takes a clientRunId, retry with the SAME one - that reconciles the original run, whatever state it reached, instead of starting and charging for a second one. On every other operation there is nothing to reconcile: the read or export simply failed, so a plain backed-off retry is the whole recovery.
- `503`: Dispatch definitively rejected (TRIGGER_DISPATCH_FAILED, credit restored) or generation paused (LLM_PAUSED).

---

[API](https://skmtc.dev/preuve/apis/preuve-agent-api.md) · [All operations](https://skmtc.dev/preuve/apis/preuve-agent-api/llms.txt) · [OpenAPI document](https://skmtc.dev/preuve/apis/preuve-agent-api/revisions/d58b3d396fa7?raw)
