# Mistral: OCR

Run Mistral OCR (mistral-ocr-latest) on a document or image URL and get markdown per page, plus optional structured annotations. Mirrors POST api.mistral.ai/v1/ocr: same request and response shape, swap only the host. Price is $0.01 per page, or $0.02 per page when any annotation option is set. pages accepts an array like [0, 1, 2] or a range string like "0,2-4"; omit it to process the whole document, in which case the service counts the PDF pages itself before quoting the price (PPTX/DOCX need explicit pages; max 1000 pages per call). Image inputs always count as one page. The body is validated before charging, and upstream failures (including pages past the end of the document) are refunded automatically. For private files, upload to storage.payweave.services first and pass the returned URL.

- Method: POST
- Path: `/ocr`
- Price: $0.01000000

## Input Schema

```json
{
  "type": "object",
  "properties": {
    "model": {
      "type": [
        "string",
        "null"
      ],
      "description": "Mistral OCR model id. Defaults to mistral-ocr-latest."
    },
    "include_image_base64": {
      "type": [
        "boolean",
        "null"
      ],
      "description": "Return base64 image data for images extracted from the document"
    },
    "image_limit": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0
        },
        {
          "type": "null"
        }
      ],
      "description": "Maximum number of images to extract"
    },
    "image_min_size": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0
        },
        {
          "type": "null"
        }
      ],
      "description": "Minimum height and width, in pixels, for an image to be extracted"
    },
    "bbox_annotation_format": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "text",
                "json_object",
                "json_schema"
              ]
            }
          },
          "required": [
            "type"
          ],
          "additionalProperties": true
        },
        {
          "type": "null"
        }
      ],
      "description": "Structured format for per-image bbox annotations (upstream accepts json_schema only). Setting this prices the call at the annotation rate."
    },
    "document_annotation_format": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "text",
                "json_object",
                "json_schema"
              ]
            }
          },
          "required": [
            "type"
          ],
          "additionalProperties": true
        },
        {
          "type": "null"
        }
      ],
      "description": "Structured format for a whole-document annotation (upstream accepts json_schema only). Setting this prices the call at the annotation rate."
    },
    "document_annotation_prompt": {
      "type": [
        "string",
        "null"
      ],
      "description": "Optional prompt guiding structured extraction over the whole document. Requires document_annotation_format. Setting this prices the call at the annotation rate."
    },
    "table_format": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "markdown",
            "html"
          ]
        },
        {
          "type": "null"
        }
      ],
      "description": "Output format for extracted tables"
    },
    "extract_header": {
      "type": "boolean",
      "description": "Extract page headers separately"
    },
    "extract_footer": {
      "type": "boolean",
      "description": "Extract page footers separately"
    },
    "confidence_scores_granularity": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "word",
            "page"
          ]
        },
        {
          "type": "null"
        }
      ],
      "description": "Granularity for OCR confidence scores: \"word\" (per-word) or \"page\" (aggregate only). Omit for no confidence scores."
    },
    "document": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "type": {
              "type": "string",
              "const": "document_url"
            },
            "document_url": {
              "type": "string",
              "format": "uri",
              "description": "Publicly reachable URL of a PDF, PPTX, or DOCX document"
            },
            "document_name": {
              "type": "string",
              "description": "Optional display name for the document"
            }
          },
          "required": [
            "type",
            "document_url"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "type": {
              "type": "string",
              "const": "image_url"
            },
            "image_url": {
              "type": "string",
              "format": "uri",
              "description": "Publicly reachable URL of a PNG, JPEG, or AVIF image"
            }
          },
          "required": [
            "type",
            "image_url"
          ],
          "additionalProperties": false
        }
      ],
      "description": "The document or image to process"
    },
    "pages": {
      "anyOf": [
        {
          "anyOf": [
            {
              "type": "array",
              "items": {
                "type": "integer",
                "minimum": 0
              },
              "maxItems": 1000
            },
            {
              "type": "string",
              "pattern": "^\\d+(-\\d+)?(,\\d+(-\\d+)?)*$"
            }
          ]
        },
        {
          "type": "null"
        }
      ],
      "description": "0-indexed pages to process: an array like [0, 1, 2] or a range string like \"0,2-4\", same grammar as upstream (max 1000 distinct pages per call). Each distinct page adds to the price. Omit (or send null or []) to process the whole document: the service then counts the PDF pages itself and prices the full document. PPTX and DOCX inputs must pass explicit pages since their page count depends on rendering. Ignored for image inputs, which always count as one page. Requesting pages beyond the end of the document may fail upstream, in which case the charge is refunded automatically."
    }
  },
  "required": [
    "document"
  ],
  "additionalProperties": false
}
```

## Output Schema

```json
{
  "type": "object",
  "properties": {
    "pages": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "index": {
            "type": "integer"
          },
          "markdown": {
            "type": "string"
          },
          "images": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "additionalProperties": true
            }
          },
          "dimensions": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "dpi": {
                    "type": "number"
                  },
                  "height": {
                    "type": "number"
                  },
                  "width": {
                    "type": "number"
                  }
                },
                "required": [
                  "dpi",
                  "height",
                  "width"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "index",
          "markdown"
        ],
        "additionalProperties": true
      }
    },
    "model": {
      "type": "string"
    },
    "document_annotation": {
      "type": [
        "string",
        "null"
      ]
    },
    "usage_info": {
      "type": "object",
      "properties": {
        "pages_processed": {
          "type": "integer"
        },
        "doc_size_bytes": {
          "type": [
            "number",
            "null"
          ]
        }
      },
      "required": [
        "pages_processed"
      ],
      "additionalProperties": true
    }
  },
  "required": [
    "pages",
    "model",
    "usage_info"
  ],
  "additionalProperties": true
}
```

## Networks

| Name | CAIP-2 | Chain ID / Cluster | Protocols |
|---|---|---|---|
| Tempo Mainnet | `eip155:4217` | 4217 | mpp |
| Solana Mainnet | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | mainnet-beta | mpp, x402 |
| Base | `eip155:8453` | 8453 | x402 |

## Accepted Currencies

| Symbol | Name | Decimals | Network | Address | Protocols |
|---|---|---|---|---|---|
| USDC.e | Bridged USDC (Stargate) | 6 | `eip155:4217` | `0x20c000000000000000000000b9537d11c60e8b50` | mpp |
| USDC | USD Coin (Solana) | 6 | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` | mpp, x402 |
| USDC | USD Coin | 6 | `eip155:8453` | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | x402 |

## How to invoke

Payment is handled automatically — the client signs the 402 challenge and retries.

### TypeScript — Tempo (mppx + fetch) ([docs](https://mpp.dev/sdk/typescript/client))

```ts
import { privateKeyToAccount } from 'viem/accounts'
import { Mppx, tempo } from 'mppx/client'

Mppx.create({
  methods: [tempo({ account: privateKeyToAccount('0x...') })],
})

const res = await fetch('https://mistral.payweave.services/ocr', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    "document": {
      "type": "",
      "document_url": "https://example.com",
      "document_name": ""
    },
    "model": "",
    "include_image_base64": false
  }),
})
const data = await res.json()
```

### TypeScript — Solana (@solana/mpp + fetch) ([docs](https://github.com/solana-foundation/mpp-sdk))

```ts
import { createKeyPairSignerFromBytes } from '@solana/kit'
import { Mppx } from 'mppx/client'
import { solana } from '@solana/mpp/client'

const signer = await createKeyPairSignerFromBytes(/* 64-byte secret key */)
Mppx.create({ methods: [solana({ signer })] })

const res = await fetch('https://mistral.payweave.services/ocr', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    "document": {
      "type": "",
      "document_url": "https://example.com",
      "document_name": ""
    },
    "model": "",
    "include_image_base64": false
  }),
})
const data = await res.json()
```

### mppx CLI ([docs](https://mpp.dev/sdk/typescript/cli))

```sh
npx mppx "https://mistral.payweave.services/ocr" -X POST -H 'Content-Type: application/json' -d '{"document":{"type":"","document_url":"https://example.com","document_name":""},"model":"","include_image_base64":false}'
```

### Tempo Wallet ([docs](https://docs.tempo.xyz/cli/wallet))

```sh
tempo request "https://mistral.payweave.services/ocr" -X POST --json '{"document":{"type":"","document_url":"https://example.com","document_name":""},"model":"","include_image_base64":false}'
```

### pay.sh — Solana Foundation ([docs](https://pay.sh))

```sh
pay --mainnet curl "https://mistral.payweave.services/ocr" -X POST -H 'Content-Type: application/json' -d '{"document":{"type":"","document_url":"https://example.com","document_name":""},"model":"","include_image_base64":false}'
```

### agentcash CLI ([docs](https://www.npmjs.com/package/agentcash))

```sh
npx agentcash fetch "https://mistral.payweave.services/ocr" -m POST -b '{"document":{"type":"","document_url":"https://example.com","document_name":""},"model":"","include_image_base64":false}' -p mpp
```

### x402 — Base / Solana USDC (x402-fetch) ([docs](https://x402.org))

```ts
import { wrapFetchWithPayment } from 'x402-fetch'
import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount('0x...') // Base USDC wallet
const fetchWithPay = wrapFetchWithPayment(fetch, account)

const res = await fetchWithPay('https://mistral.payweave.services/ocr', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    "document": {
      "type": "",
      "document_url": "https://example.com",
      "document_name": ""
    },
    "model": "",
    "include_image_base64": false
  }),
})
const data = await res.json()
```

### x402 — agentcash CLI

```sh
npx agentcash fetch "https://mistral.payweave.services/ocr" -m POST -b '{"document":{"type":"","document_url":"https://example.com","document_name":""},"model":"","include_image_base64":false}' -p x402
```
