# OCR (texte d’un document)

> Référence de POST /v1/ocr : extraire le texte d’un PDF ou d’une image avec moon-ocr-1, qui tourne sur nos serveurs en France sans rien envoyer à un fournisseur.

`POST /v1/ocr` renvoie le texte d’un PDF ou d’une image, page par page, en Markdown. Une page qui a déjà une couche de texte (un PDF exporté depuis un traitement de texte) est lue directement ; une page scannée ou une photo est lue par reconnaissance de caractères.

```http
POST https://api.realmoon.ai/v1/ocr
```

- Authentification : clé `sk-moon-…` avec la portée `inference` (voir [Authentification](https://realmoon.ai/documentation/api/authentification/)).
- Corps : `multipart/form-data` (avec l’en-tête `Content-Length`) ou JSON, dans la forme de l’API OCR de Mistral.
- Réponse : le texte de chaque page lue.

Le seul modèle est `moon-ocr-1`. Il tourne sur nos serveurs en France : le document n’est envoyé à aucun fournisseur et n’est pas gardé une fois la réponse donnée.

## Paramètres

### En multipart

| Champ | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `file` (ou `document`) | fichier | oui | Le PDF ou l’image (PNG, JPEG, WebP, GIF), 30 Mo au plus. Un seul fichier. |
| `model` | chaîne | non | `moon-ocr-1` (par défaut). |
| `pages` | chaîne | non | Les pages à lire, numérotées à partir de 0 et séparées par des virgules : `0,2,5`. |

### En JSON

| Paramètre | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `document` | objet ou chaîne | oui | `{"type": "document_url", "document_url": "data:application/pdf;base64,..."}` ou `{"type": "image_url", "image_url": "data:image/png;base64,..."}`. Une chaîne seule (URL `data:` ou base64) est aussi acceptée. |
| `model` | chaîne | non | `moon-ocr-1` (par défaut). |
| `pages` | tableau d’entiers | non | Les pages à lire, à partir de 0. |
| `include_image_base64` | booléen | non | Seule la valeur `false` est acceptée : les images des pages ne sont pas renvoyées. |
| `id` | chaîne | non | Accepté, sans effet. |

En JSON, tout autre paramètre est refusé avec `400 unknown_parameter`.

> [!WARNING]
> **Pas de document par adresse**
>
> L’API ne télécharge pas un document à partir d’une adresse `https://` (`400 url_not_supported`). Envoyez le fichier lui-même, en multipart ou en base64.

### Pages

- Sans `pages`, tout le document est lu, jusqu’à 50 pages. Au-delà, l’API répond `400 too_many_pages` : choisissez les pages, et faites plusieurs requêtes pour un long document.
- Une image a une seule page, la page 0.
- Une page déjà demandée n’est lue qu’une fois.

## Exemple

Les SDK d’OpenAI n’ont pas de méthode pour ce point d’accès : appelez-le en HTTP.

```bash title="cURL"
curl https://api.realmoon.ai/v1/ocr \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -F model=moon-ocr-1 \
  -F file=@facture.pdf \
  -F pages=0,1
```

```python title="Python"
import os
import requests

with open("facture.pdf", "rb") as document:
    response = requests.post(
        "https://api.realmoon.ai/v1/ocr",
        headers={"Authorization": f"Bearer {os.environ['MOONAI_API_KEY']}"},
        data={"model": "moon-ocr-1", "pages": "0,1"},
        files={"file": ("facture.pdf", document, "application/pdf")},
        timeout=100,
    )
response.raise_for_status()
for page in response.json()["pages"]:
    print(page["index"], page["source"])
    print(page["markdown"])
```

```javascript title="JavaScript"
import fs from 'node:fs';

const form = new FormData();
form.append('model', 'moon-ocr-1');
form.append('pages', '0,1');
form.append('file', new Blob([fs.readFileSync('facture.pdf')], { type: 'application/pdf' }), 'facture.pdf');

const response = await fetch('https://api.realmoon.ai/v1/ocr', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.MOONAI_API_KEY}` },
  body: form,
});
const result = await response.json();
for (const page of result.pages) console.log(page.index, page.source, page.markdown);
```

Le même appel en JSON, avec le document en base64 :

```bash title="Corps JSON"
curl https://api.realmoon.ai/v1/ocr \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"model\": \"moon-ocr-1\", \"document\": {\"type\": \"document_url\", \"document_url\": \"data:application/pdf;base64,$(base64 -w0 facture.pdf)\"}, \"pages\": [0, 1]}"
```

## Réponse

```json title="Réponse"
{
  "model": "moon-ocr-1",
  "pages": [
    {
      "index": 0,
      "markdown": "# Facture n° 2026-118\n\nDate : 4 novembre 2026\n\n| Désignation | Montant |\n| --- | --- |\n| Prestation | 1 200,00 € |",
      "source": "text",
      "images": [],
      "dimensions": null
    },
    {
      "index": 1,
      "markdown": "Conditions de paiement : 30 jours.",
      "source": "ocr",
      "images": [],
      "dimensions": null
    }
  ],
  "usage_info": { "pages_processed": 2, "doc_size_bytes": 184320 },
  "usage": { "pages": 2, "pages_not_read": 0, "credits": 0 }
}
```

La valeur de `credits` est fictive.

| Champ | Type | Description |
| --- | --- | --- |
| `model` | chaîne | Toujours `moon-ocr-1`. |
| `pages[].index` | entier | Numéro de la page, à partir de 0. |
| `pages[].markdown` | chaîne | Le texte de la page, en Markdown. |
| `pages[].source` | chaîne | `text` : lue dans la couche de texte du PDF. `ocr` : lue par reconnaissance de caractères. |
| `pages[].images`, `pages[].dimensions` | tableau, `null` | Toujours `[]` et `null`, gardés pour la compatibilité avec la forme de Mistral. |
| `usage_info.pages_processed`, `usage_info.doc_size_bytes` | entier | Pages lues et taille du document en octets, comme chez Mistral. |
| `usage.pages` | entier | Pages lues et facturées. |
| `usage.pages_not_read` | entier | Pages demandées que le temps de la requête n’a pas permis de lire. Elles ne sont ni renvoyées ni facturées. |
| `usage.credits` | entier | Crédits facturés. |

| En-tête | Valeur |
| --- | --- |
| `X-Moon-Hosting` | `fr` : document lu sur nos serveurs en France. |
| `X-Moon-Blur` | `not_needed` : le document ne quitte pas nos serveurs, Moon Blur n’est pas nécessaire. |
| `X-Moon-Request-Id`, `X-Moon-Prompt-Storage` | Comme pour toute requête. |

## Coûts

Le prix est fixe par page lue ; il figure dans `GET /v1/models?type=ocr` (`pricing.credits_per_unit`, `billing: flat`) et dans l’onglet « Modèles » du portail. La requête retient le prix des pages demandées, puis ne facture que les pages réellement lues. Un document illisible ou une requête qui échoue ne coûte rien.

## Limites

| Limite | Valeur |
| --- | --- |
| Taille du document | 30 Mo |
| Pages par requête | 50 |
| Durée d’une requête | 85 secondes environ ; les pages non lues à temps ne sont ni renvoyées ni facturées |
| Requêtes en cours par workspace | 2 |

Le service de lecture est partagé : quand il est occupé par d’autres requêtes, l’API répond `429 too_many_concurrent` ou `503 ocr_busy`. Pour un gros document, envoyez quelques pages à la fois et lancez les requêtes l’une après l’autre.

## Erreurs

| HTTP | `code` | Signification |
| --- | --- | --- |
| 400 | `missing_required_parameter` | Fichier ou `document` absent. |
| 400 | `unknown_parameter` | Paramètre inconnu (en JSON). |
| 400 | `unsupported_parameter` | `include_image_base64` à `true`. |
| 400 | `url_not_supported` | Document donné par une adresse `https://`. |
| 400 | `unsupported_format` | Ni un PDF, ni une image PNG, JPEG, WebP ou GIF. |
| 400 | `invalid_image` | Image illisible, ou de plus de 40 mégapixels. |
| 400 | `encrypted_document` | PDF protégé par un mot de passe. |
| 400 | `invalid_document` | PDF sans aucune page. |
| 400 | `too_many_pages` | Plus de 50 pages sans `pages`. |
| 400 | `null` | Numéro de page qui n’existe pas, page autre que 0 pour une image, document vide, base64 invalide (`param` le nomme). |
| 403 | `org_policy` | Les règles de votre organisation refusent l’API ou ce modèle. |
| 404 | `model_not_found` | Modèle autre que `moon-ocr-1`. |
| 411 | `length_required` | Envoi multipart sans en-tête `Content-Length`. |
| 413 | `file_too_large`, `request_too_large` | Document de plus de 30 Mo. |
| 422 | `unreadable_document` | Document illisible ou trop lourd à lire. |
| 429 | `too_many_concurrent` | Trop de requêtes OCR en cours pour ce workspace, ou pour le service. |
| 503 | `ocr_busy` | Service de lecture occupé : réessayez après `Retry-After` (10 secondes). |
| 504 | `ocr_timeout` | Lecture trop longue : envoyez moins de pages. |

Les erreurs de clé, de solde et de plafonds sont dans [Erreurs](https://realmoon.ai/documentation/api/erreurs/).

## Voir aussi

- [Confidentialité](https://realmoon.ai/documentation/api/confidentialite/#garde) : ce que Moon AI garde, et ne garde pas, d’un document.
- [Modèles](https://realmoon.ai/documentation/api/modeles/#medias) : les champs `max_pages` et `max_file_mb`.

---

Documentation Moon AI › API développeur › OCR. Page : https://realmoon.ai/documentation/api/ocr/. Modifiée le 5 novembre 2026.

© 2026 Stellarr Studio SAS. Tous droits réservés. Moon AI, Moon Blur et Stellarr Studio sont des marques déposées à l’INPI.
