---
title: "Submit one analysis"
method: POST
path: "/v1/analyses"
tags: ["Analysis"]
---

# Submit one analysis

`POST /v1/analyses`

## Request

- Base URL: `https://carbonguru.io`
- URL: `https://carbonguru.io/v1/analyses`
- Auth: HTTP bearer

A JSON body declares exactly one input: a url, text, html with the url it came from, or structured items with the country they were bought in. Two inputs is a 422, and each answers 202 with the session id.

A multipart/form-data body is a file. `country_code` is required with it, because a file carries no country of its own and nothing is assumed: the footprint is calculated for the country the caller declares, and prices with no stated currency are read in that country's currency. `kind` chooses the backend, and is otherwise decided by the extension — .pdf .docx .doc .txt .md are documents, .csv .xlsx .xls .tsv .ofx .qfx .qif .iif are accounting files. A document over 100 KB or an accounting file over 1 MB is refused here with a 413 before it is forwarded.

The two kinds finish differently. An accounting file is analysed off the request and answers 202 with links.import beside the session links. A DOCUMENT IS ANALYSED INSIDE THE REQUEST by the main app's single worker process, so the request is held for the length of the analysis — up to 180 seconds — and answers 200 with status 'completed', because by then the work is done.

## Headers

- `Idempotency-Key` string

## Request body

- AnalysisRequest: Exactly one input. html and url together are one input, not two.
  - `url` string: A product or cart page the platform fetches, or the address html came from.
  - `context_type` 'product' | 'cart' | 'multi_product' | 'order_list'
  - `timeout` integer
  - `text` string: Freeform text: a shopping list, a receipt, an order confirmation.
  - `html` string: Page html the caller already holds. Needs url.
  - `source_name` string: A label for a text analysis.
  - `items` AnalysisItem[]: Structured items. Needs country_code.
    - `product_name` string, required
    - `description` string
    - `category` string
    - `quantity` integer
    - `price` object, required
      - `current_price` number, required
      - `currency` string: ISO 4217. Omitted takes the declared country's currency.
  - `country_code` string: The country these items were bought in. Required with items; nothing is defaulted.

## Response `200`

A document, analysed inside the request. status is 'completed'.

- AnalysisAccepted
  - `session_id` string, required
  - `status` 'processing' | 'completed', required: completed only for a document upload, which finishes inside the request.
  - `links` object, required
    - `session` string
    - `progress` string
    - `import` string: Present for an accounting file: its import record.

## Other responses

- `202`: Accepted. The analysis runs off the request.
- `401`: No valid credential. Every authentication failure returns this one document.
- `402`: The account's plan does not include this capability. Carries min_tier and upgrade_url.
- `403`: A missing scope, an exhausted analysis allowance, or an object that is not the caller's.
- `409`: An Idempotency-Key was reused with a different body (idempotency_key_reuse), or a request under the same key is still running (idempotency_in_progress).
- `413`: The uploaded file is over the limit for its kind: 100 KB for a document, 1 MB for an accounting file.
- `422`: The request's fields are wrong. errors[] names them.
- `429`: The platform's rate limit. Retry-After carries its own stated wait.
- `502`: The platform did not complete the request.

---

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