<!-- Generated from the fr/docs page by the site build (site/integrations/md-twins.mjs); never edit by hand. -->

# Guide de démarrage

OpenQASM 3 en entrée, counts canoniques en sortie. Le chemin heureux complet ; chaque champ figure dans la [référence de l'API](https://pauli.xyz/reference), la spécification brute sur [`/openapi.json`](https://pauli.xyz/openapi.json).

## 0 · Obtenir une clé

[Créez un espace de travail](https://pauli.xyz/fr/signup), obtenez une clé d'administrateur ; chaque client ci-dessous la lit depuis l'environnement :

```
export PAULI_API_KEY=pauli_sk_…   # shown once at creation; rotate any time
```

## 1 · Qiskit

Chaque appareil du registre est un `BackendV2` Qiskit : choisissez-en un, exécutez, lisez les counts dans l'ordre de clés propre à Qiskit. Les exécutions restent épinglées au backend choisi, jamais de repli silencieux :

```
pip install qiskit-pauli   # Python ≥ 3.10
```

```
from qiskit import QuantumCircuit
from qiskit_pauli import PauliProvider

qc = QuantumCircuit(3, 3)                 # GHZ
qc.h(0); qc.cx(0, 1); qc.cx(0, 2)
qc.measure(range(3), range(3))

provider = PauliProvider()                # reads PAULI_API_KEY
backend = provider.least_busy(simulator=True)  # drop simulator=True for hardware
counts = backend.run(qc, shots=1000).result().get_counts()
print(counts)                             # {'000': 489, '111': 511}
```

Le reste de cette page passe par `provider.client`, le client typé complet sous chaque backend : l'argent en `Decimal` exact (un float lève une exception), une clé d'idempotence à chaque soumission, des exceptions liées aux codes stables ci-dessous.

## 2 · Estimer la flotte (gratuit)

Un seul appel chiffre *votre* circuit sur chaque appareil éligible, avec file d'attente prévue, fidélité et exclusions motivées :

```
from qiskit import qasm3

client = provider.client                  # the full pauli-sdk client
fleet = client.jobs.estimate(qasm3.dumps(qc), shots=1000)
for e in fleet.estimates:                 # cheapest first
    print(e.device, e.amount, e.predicted_queue_seconds, e.fidelity_score)
for x in fleet.excluded:                  # reasoned exclusions, complete
    print(x.device, x.reasons[0].code)
```

```
ionq.simulator 0.000000 1.0 1.0
ionq.qpu.forte-enterprise-1 2.700000 6871.0 0.953
```

## 3 · Soumettre avec une politique

Choisissez `cheapest`, `fastest`, `highest_fidelity` ou `balanced` ; épinglez un appareil, ou contraignez par fournisseur, prix, file ou région. Le job revient aussitôt avec la décision de routage et le coût exact ; chaque soumission porte une clé d'idempotence (générée automatiquement sauf si vous passez la vôtre), donc une nouvelle tentative ne peut jamais soumettre deux fois :

```
job = client.jobs.submit(qasm3.dumps(qc), shots=1000,
                         policy="highest_fidelity", only=["ionq"],
                         allow_simulator_fallback=True, max_spend_usd="10.00",
                         idempotency_key="exp-042-run-7",
                         webhook_url="https://example.com/hooks/pauli")
print(job.routing_decision.selected_device, job.cost_estimate.amount)
```

Un échec avant exécution se rabat sur le meilleur appareil suivant, sauf avec `allow_fallback=False` ; chaque saut est journalisé, et vous ne payez que l'appareil qui a exécuté.

## 4 · Interroger, ou recevoir le webhook

```
job.wait()   # jittered backoff to a terminal state; timeout=… to bound it
# created → validating → estimating → queued → transpiling → submitted → running → completed
```

Avec un `webhook_url` (https uniquement), chaque transition d'état fait un POST une fois, signé avec le secret webhook de la clé émettrice (affiché à sa création) ; dédupliquez sur `X-Pauli-Event-Id` :

```
import hashlib, hmac, time

def verify(secret: str, body: bytes, header: str, tolerance: int = 300) -> bool:
    pairs = [p.split("=", 1) for p in header.split(",")]  # header: X-Pauli-Signature
    t = next(v for k, v in pairs if k == "t")
    if abs(time.time() - int(t)) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
    return any(hmac.compare_digest(expected, v) for k, v in pairs if k == "v1")
```

Le SDK fournit cette recette : `pauli_sdk.webhooks.unwrap(body, headers, secret=…)`.

## 5 · Résultats : un seul ordre de bits

```
{
  "counts": {"000": 489, "111": 511},
  "bit_ordering": "cbit0_left",
  "register_map": {"c": ["q[0]", "q[1]", "q[2]"]},
  "metadata": {"provider_job_id": "…", "calibration_snapshot_id": "…"},
  "insights": {"shape": "cat_pair", "confidence": "high", "headline": "GHZ-like cat state: …"},
  "billing": {"billed_usd": "2.470000"}
}
```

**La convention des counts** : le caractère le plus à gauche de chaque clé est le bit classique 0 du premier registre déclaré ; les registres s'aplatissent dans l'ordre de déclaration. Chaque fournisseur s'y normalise ; le code d'analyse ne bifurque jamais.

**Insights** : une classification indicative de la forme de l'histogramme (état chat, uniforme, peigne périodique, tavelure de Porter-Thomas, …) avec un titre en langage clair et une confiance ajustée au nombre de shots, dérivée des seuls counts. Un guide de lecture, jamais une surface de scoring.

## 6 · Vos propres identifiants (BYOK)

Enregistrez des identifiants (/console/credentials ou `PUT /v1/credentials/{provider}`) et les jobs de ce fournisseur s'exécutent sous votre compte : le fournisseur vous facture directement ; votre portefeuille ne paie que les frais de plateforme ([tarifs](https://pauli.xyz/fr/pricing)). Estimations, statut et résultats affichent `byok` ; le repli ne traverse jamais les modes de facturation.

## 7 · Agents (MCP)

Model Context Protocol sur `https://pauli.xyz/mcp` (Streamable HTTP), même clé bearer. Les outils reflètent le flux de cette page.

```
claude mcp add --transport http pauli https://pauli.xyz/mcp \
  --header "Authorization: Bearer $PAULI_API_KEY"
```

## 8 · Payer depuis un agent

Une soumission payante au-delà de votre solde renvoie `402` `billing.insufficient_credits` ; son `detail` est un défi de paiement nommant le manque, l'endpoint de rechargement et la confirmation du crédit. Approvisionnez (les rechargements renvoient un `checkout_url` hébergé qu'un humain complète), puis resoumettez avec la même `Idempotency-Key`. Le rechargement automatique (`PATCH /v1/billing/settings`) réapprovisionne depuis une carte enregistrée avant que les jobs ne voient le 402. Les résultats d'outils MCP portent le même défi, mot pour mot.

Les autres 402, `billing.monthly_cap_exceeded` et `billing.key_cap_exceeded`, sont des plafonds que vous fixez ; ils ne portent pas de défi. Relevez le plafond si la dépense est voulue.

---

## Erreurs

Chaque erreur est `{"error": {"code", "message", "detail?", "request_id"}}` avec un code stable ; le registre est [`/public/errors`](https://pauli.xyz/public/errors). Citez le `request_id` au support. Les premières rencontrées :

| Code | Signification |
| --- | --- |
| program.invalid | L'OpenQASM 3 n'a pas été parsé ; le detail porte ligne et colonne. |
| routing.no_feasible_device | Rien ne peut exécuter ce programme sous vos contraintes ; le detail liste les raisons par appareil. |
| billing.insufficient_credits | 402 : approvisionnez le manque et resoumettez (section 8). |
