API pour flux de travail validés

Validez le flux de travail avant d'utiliser l'API

Commencez dans le poste de travail, confirmez que le résultat vérifié correspond à votre flux de travail, puis utilisez l'API pour des extractions reproductibles.

Base: https://pdf2text.ai/api/v1

Authentification

Toutes les requêtes API nécessitent un jeton Bearer dans l'en-tête Authorization. Générez des clés depuis les paramètres du compte après avoir validé un flux de travail reproductible.

Gérer les clés API
# Set your API key
export P2T_API_KEY="your_api_key_here"

# Include in all requests
curl -H "Authorization: Bearer $P2T_API_KEY" ...
import requests
import os

API_KEY = os.environ["P2T_API_KEY"]
headers = {"Authorization": f"Bearer {API_KEY}"}
const API_KEY = process.env.P2T_API_KEY;

const headers = {
  'Authorization': `Bearer ${API_KEY}`
};

Limites d'utilisation

Le plan Firm inclut 1500 pages par mois pour les flux de travail vérifiés dans le poste de travail et les extractions API validées. Chaque page traitée utilise une page de ce quota.

L'utilisation est mesurée en pages traitées, et non en appels API. L'importation de fichiers et le téléchargement de résultats ou d'exports n'utilisent pas de pages, mais relancer une extraction traite à nouveau ces pages et les décompte de nouveau.

Les formats pris en charge pour l'importation sont PDF, PNG, JPEG et WebP, jusqu'à 50 MiB par fichier. Le déploiement actuel limite également la requête multipart complète à 100 MiB, fichiers et surcharge du formulaire compris. Les importations sont limitées à 20 fichiers par requête, 100 fichiers par groupe, 500 pages par document ou exécution et 1 000 pages stockées par groupe. Les images peuvent atteindre 20 000 pixels de côté et 40 mégapixels ; les pages PDF qui dépasseraient ces limites de rastérisation à la résolution de rendu OCR sont rejetées.

Il n'existe pas de quota distinct d'appels API. Les extractions sont asynchrones et entrent dans la file de traitement : leur durée peut donc varier selon la taille des documents et la charge du système.

Les limites de requêtes pour usage équitable sont par défaut de 30 importations, 60 lancements d'exécution et 600 lectures ou exports par compte et par heure. Une réponse 429 inclut Retry-After ; attendez ce délai avant de réessayer.

Utilisez le poste de travail pour valider les mises en page des documents, les règles de vérification et les formats d'export avant de vous appuyer sur l'automatisation par API.

Comparer les plans
POST

Importer des documents

Importez un ou plusieurs fichiers PDF, PNG, JPEG ou WebP pour créer un groupe de documents. Les octets des fichiers, le nombre de pages et les dimensions des images sont vérifiés avant tout enregistrement. Une importation réussie renvoie 201 Created avec le page_count vérifié pour chaque document.

Point de terminaison

POST /api/v1/documents/upload/

Paramètres

file / files binary PDF, PNG, JPEG ou WebP (obligatoire ; répétez files pour importer plusieurs fichiers)
grouping_id uuid Facultatif. Ajouter à l'un de vos groupes API existants. Les espaces de travail anonymes ne peuvent pas être revendiqués par UUID, et une exécution active rend son groupe immuable jusqu'à la fin.
document_type string Optionnel. Indice de classification.
password string Facultatif. Ouvre les PDF protégés par mot de passe dans cette requête. Il sert uniquement à ouvrir les fichiers et n'est pas conservé. Sans lui, un tel PDF renvoie encrypted_pdf ; un mot de passe erroné renvoie pdf_password_incorrect, et des erreurs répétées pour un même fichier renvoient 429.
# Upload a PDF file
curl -X POST https://pdf2text.ai/api/v1/documents/upload/ \
  -H "Authorization: Bearer $P2T_API_KEY" \
  -F "file=@invoice.pdf"

# Add to existing group
curl -X POST https://pdf2text.ai/api/v1/documents/upload/ \
  -H "Authorization: Bearer $P2T_API_KEY" \
  -F "file=@invoice2.pdf" \
  -F "grouping_id=a1b2c3d4-..."
import requests

url = "https://pdf2text.ai/api/v1/documents/upload/"

# Upload single file
with open("invoice.pdf", "rb") as f:
    response = requests.post(
        url,
        headers=headers,
        files={"file": f}
    )

data = response.json()
group_id = data["group_id"]
const { readFile } = require('node:fs/promises');

const form = new FormData();
form.append(
  'file',
  new Blob([await readFile('invoice.pdf')], { type: 'application/pdf' }),
  'invoice.pdf'
);

const response = await fetch(
  'https://pdf2text.ai/api/v1/documents/upload/',
  {
    method: 'POST',
    headers,
    body: form
  }
);
if (!response.ok) throw new Error(`Upload failed: ${response.status}`);
const { group_id } = await response.json();
201 Created
{
  "status": "success",
  "group_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "documents": [
    {
      "doc_id": 42,
      "uid": "1847f600-...",
      "grouping_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "original_filename": "invoice.pdf",
      "file_type": "pdf",
      "page_count": 3,
      "status": "pending"
    }
  ]
}

Ajoutez des fichiers à un groupe uniquement avant sa première exécution. Pour les factures suivantes, créez un nouveau groupe ; sinon, une exécution sans filtre traite tous les documents déjà présents dans ce groupe.

POST

Lancer l'extraction

Lancez le traitement asynchrone d'un groupe de documents. Utilisez le routage automatique lorsque PDF2TEXT doit classer les documents avant l'extraction.

Envoyez un en-tête Idempotency-Key avec chaque requête de lancement. Répéter la même clé avec le même corps renvoie la même exécution ; réutiliser la clé pour une requête différente renvoie 409. Après un échec définitif, utilisez une nouvelle clé pour créer volontairement une exécution de remplacement. Une exécution nouvellement mise en file renvoie 202 Accepted. Une seule exécution par groupe peut être active à la fois, et les exécutions actives réservent les pages du compte qu'elles peuvent traiter.

Une réponse 202 confirme que l'exécution a été acceptée, et non que chaque page demandée est couverte. Si le solde partagé du compte est inférieur à l'exécution, l'API traite les pages réservées et se termine en statut partial avec credit_limit_reached=true. Vérifiez le statut final de l'exécution avant de considérer l'import comme terminé.

Les URL de callback doivent utiliser HTTPS public et ne peuvent pas rediriger vers une autre destination. La livraison est asynchrone, avec un délai d'expiration de requête de 10 secondes, et effectue jusqu'à quatre nouvelles tentatives en cas d'erreurs de connexion transitoires, de réponses HTTP 429 et HTTP 5xx, avec des intervalles d'attente de 30 secondes, 2 minutes et 10 minutes.

Lorsque callback_secret est fourni, vérifiez X-PDF2TEXT-Signature en calculant un HMAC-SHA256 sur le corps exact de la requête et en le comparant à la valeur sha256=. Utilisez X-PDF2TEXT-Run-ID ou X-PDF2TEXT-Idempotency-Key pour dédupliquer les livraisons.

The callback JSON body is {"event": "idp.run.completed", "run": {...}}; run uses the same full result shape as GET ?include=results. A signature header is sent only when callback_secret was included in the start request.

Point de terminaison

POST /api/v1/groups/{group_id}/runs/

Corps de la requête

auto_route boolean Classification automatique (par défaut : true)
extraction_mode enum auto, raw_text, financial_table, general_table ou unified. Utilisez template_id ou template_slug pour un schéma personnalisé.
template_id / template_slug uuid / string Utilisez-en exactement un pour imposer un modèle spécifique
selected_pages array Liste facultative non vide de {docUid, pageNumber} ; des pages invalides entraînent le rejet de toute la requête
construction_project_id uuid Projet facultatif appartenant au compte API
callback_url string URL du webhook
callback_secret string Clé secrète de signature HMAC
# Start extraction with auto-routing
curl -X POST https://pdf2text.ai/api/v1/groups/$GROUP_ID/runs/ \
  -H "Authorization: Bearer $P2T_API_KEY" \
  -H "Idempotency-Key: invoice-import-123" \
  -H "Content-Type: application/json" \
  -d '{"auto_route": true}'
# Start extraction run
url = f"https://pdf2text.ai/api/v1/groups/{group_id}/runs/"

response = requests.post(
    url,
    headers={**headers, "Idempotency-Key": "invoice-import-123"},
    json={"auto_route": True}
)

run_data = response.json()
run_id = run_data["run_id"]
// Start extraction run
const response = await fetch(
  `https://pdf2text.ai/api/v1/groups/${groupId}/runs/`,
  {
    method: 'POST',
    headers: {
      ...headers,
      'Idempotency-Key': 'invoice-import-123',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ auto_route: true })
  }
);

const { run_id } = await response.json();
202 Accepted
{
  "status": "success",
  "run_id": "b3143b91-...",
  "job_id": "idp-run-b3143b91-...",
  "group_name": "ocr_job_a1b2c3d4...",
  "idempotent_replay": false,
  "run": {
    "id": "b3143b91-...",
    "status": "queued",
    "job_id": "idp-run-b3143b91-...",
    "total_pages": 3,
    "pages_processed": 0
  }
}
GET

Récupérer les résultats

Interrogez le point de terminaison d'exécution ou utilisez des webhooks pour récupérer les résultats d'extraction. Exportez en JSON ou Excel.

La réponse d'exécution par défaut est légère pour permettre des interrogations fréquentes et n'est jamais mise en cache. Lisez run.status dans l'objet run imbriqué. Les statuts finaux sont complete, partial et error. Après un statut final, demandez include=results une fois pour récupérer full_text, structured_output et documents.

credits_remaining est conservé pour la compatibilité et enregistre le solde historique après cette exécution. credits_remaining_after_run désigne explicitement la même valeur historique, tandis que account_credits_remaining indique le solde partagé actuel du compte au moment où la réponse est générée.

Points de terminaison

GET /api/v1/runs/{run_id}/ GET /api/v1/runs/{run_id}/?include=results GET /api/v1/runs/{run_id}/export.json GET /api/v1/runs/{run_id}/export.xlsx GET /api/v1/runs/{run_id}/export.xlsx?date_format=MM/DD/YYYY

Pour les relevés bancaires, export.xlsx contient aussi des feuilles CSV QuickBooks et CSV Xero. Leurs dates suivent le format enregistré sur votre compte, ou à défaut l'ordre utilisé dans le pays du relevé. Passez date_format (DD/MM/YYYY, MM/DD/YYYY, YYYY/MM/DD ou YYYY-MM-DD) pour le choisir ; les autres feuilles restent en YYYY-MM-DD.

Codes de statut de réponse

200 401 404
# Lightweight status poll
curl https://pdf2text.ai/api/v1/runs/$RUN_ID/ \
  -H "Authorization: Bearer $P2T_API_KEY"

# Fetch completed results once, then export
curl "https://pdf2text.ai/api/v1/runs/$RUN_ID/?include=results" \
  -H "Authorization: Bearer $P2T_API_KEY"

curl -o results.xlsx \
  https://pdf2text.ai/api/v1/runs/$RUN_ID/export.xlsx \
  -H "Authorization: Bearer $P2T_API_KEY"
import time

run_url = f"https://pdf2text.ai/api/v1/runs/{run_id}/"
terminal = {"complete", "partial", "error"}
delay = 2

# Poll lightweight state with bounded exponential backoff
while True:
    response = requests.get(run_url, headers=headers)
    if response.status_code == 429:
        retry_after = int(response.headers.get("Retry-After", delay))
        time.sleep(retry_after)
        delay = min(30, max(10, delay * 2))
        continue
    response.raise_for_status()
    run = response.json()["run"]

    if run["status"] in terminal:
        break

    time.sleep(delay)
    delay = min(30, max(10, delay * 2))

if run["status"] == "error":
    raise RuntimeError(run["error_message"])

results = requests.get(run_url, params={"include": "results"}, headers=headers).json()["run"]

excel = requests.get(
    f"{run_url}export.xlsx",
    headers=headers
)
with open("results.xlsx", "wb") as f:
    f.write(excel.content)
// Poll lightweight state
const pollResults = async (runId) => {
  const runUrl = `https://pdf2text.ai/api/v1/runs/${runId}/`;
  const terminal = new Set(['complete', 'partial', 'error']);
  let delay = 2000;
  while (true) {
    const response = await fetch(runUrl, { headers });
    if (response.status === 429) {
      const retryAfter = Number(response.headers.get('Retry-After') || delay / 1000);
      await new Promise(r => setTimeout(r, retryAfter * 1000));
      delay = Math.min(30000, Math.max(10000, delay * 2));
      continue;
    }
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    const { run } = await response.json();

    if (terminal.has(run.status)) {
      if (run.status === 'error') throw new Error(run.error_message);
      const resultResponse = await fetch(`${runUrl}?include=results`, { headers });
      return (await resultResponse.json()).run;
    }

    await new Promise(r => setTimeout(r, delay));
    delay = Math.min(30000, Math.max(10000, delay * 2));
  }
};

const results = await pollResults(runId);
Réponse avec include=results
{
  "status": "success",
  "run": {
    "id": "b3143b91-...",
    "status": "complete",
    "total_pages": 3,
    "pages_processed": 3,
    "credits_remaining_after_run": 497,
    "account_credits_remaining": 497,
    "full_text": "...",
    "structured_output": { /* grouped output */ },
    "documents": [
      {
        "doc_id": 42,
        "document_name": "invoice.pdf",
        "ocr_text": "...",
        "structured_output": { /* document output */ }
      }
    ]
  }
}
GET

Modèles

Listez les modèles d'extraction disponibles. Utilisez les identifiants de modèles pour forcer des schémas d'extraction spécifiques.

Point de terminaison

GET /api/v1/templates/
Gérer les modèles
# List available templates
curl https://pdf2text.ai/api/v1/templates/ \
  -H "Authorization: Bearer $P2T_API_KEY"
# List available templates
response = requests.get(
    "https://pdf2text.ai/api/v1/templates/",
    headers=headers
)

templates = response.json()["templates"]
for t in templates:
    print(f"{t['name']}: {t['id']}")
// List available templates
const response = await fetch(
  'https://pdf2text.ai/api/v1/templates/',
  { headers }
);

const { templates } = await response.json();
templates.forEach(t => console.log(`${t.name}: ${t.id}`));
Réponse
{
  "status": "success",
  "templates": [
    {
      "id": "198aa5be-ea8b-4d67-bdb5-625f5d7d29e8",
      "slug": "invoice",
      "name": "Invoice",
      "description": "Standard invoice extraction",
      "extraction_mode": "financial_table"
    },
    {
      "id": "4317707a-f0da-4c2f-a1ec-d0119d96b55c",
      "slug": "receipt",
      "name": "Receipt",
      "description": "Receipt and expense extraction",
      "extraction_mode": "financial_table"
    }
  ]
}

Besoin d'aide ?

Utilisez la file de vérification pour examiner les champs extraits et conserver le contexte de vérification.