# Exécuter un traitement par lot

Créez, importez, suivez et téléchargez les résultats de vos traitements par lot.

Pour consulter la référence API complète, avec l’ensemble des paramètres disponibles et des champs de réponse, accédez à la [documentation de l’API Batch Jobs](https://docs.stripe.com/api/v2/core/batch-jobs.md?api-version=preview).

Pour effectuer un traitement par lots, procédez comme suit&nbsp;:

1. [Créez une tâche par lots](https://docs.stripe.com/batch-api/create.md#create-a-batch-job) et spécifiez l’endpoint API cible.
2. [Téléchargez le fichier d’entrée](https://docs.stripe.com/batch-api/create.md#upload-the-input-file) avec vos requêtes par lots.
3. [Suivre l’état du traitement](https://docs.stripe.com/batch-api/create.md#monitor-job-status) via des webhooks ou des sondages.
4. [Télécharger les résultats](https://docs.stripe.com/batch-api/create.md#download-the-results).

## Créer un traitement par lot

Pour commencer, créez un traitement par lots en envoyant une requête `POST` à `/v2/core/batch_jobs`. Spécifiez l’endpoint cible et les éventuelles options de traitement&nbsp;:

```curl
curl -X POST https://api.stripe.com/v2/core/batch_jobs \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-09-30.preview" \
  --json '{
    "endpoint": {
        "path": "/v1/subscriptions/:id/migrate",
        "http_method": "post"
    },
    "skip_validation": false
  }'
```

Le type de contenu de cette requête est un fichier JSON. Celui-ci renvoie un objet de traitement par lots avec un état `ready_for_upload`. L’URL du chargement et son délai d’expiration se trouvent dans le champ `status_details`&nbsp;:

```json
{
  "id": "batchv2_AbCdEfGhIjKlMnOpQrStUvWxYz",
  "object": "v2.core.batch_job",
  "created": "2026-03-09T20:55:31.000Z",
  "skip_validation": false,
  "status": "ready_for_upload",
  "status_details": {
    "ready_for_upload": {
      "upload_url": {
        "expires_at": "2026-03-09T21:00:31.000Z",
        "url": "https://stripeusercontent.com/files/upload/..."
      }
    }
  }
}
```

The contents of `status_details` depend on the `status` of the batch job. When `status` is `ready_for_upload`, `status_details` contains the presigned upload URL and its expiration timestamp. A presigned URL includes its own authorization, so you can upload your file to it without your API key. The URL accepts only `PUT` requests and expires 5 minutes after you create the batch job.

### Paramètres

| Paramètre | Obligatoire | Description |
| --- | --- | --- |
| `endpoint.path` | Oui | Endpoint API à cibler (par exemple, `/v1/subscriptions/:id/migrate`). Consultez les [endpoints pris en charge](https://docs.stripe.com/batch-api/supported-endpoints.md). |
| `endpoint.http_method` | Oui | The HTTP method of the target endpoint, either `post` or `delete`. Batch jobs don’t support `get`. |
| `skip_validation` | Non | Défini sur `true` pour ignorer la validation du fichier d’entrée et commencer immédiatement le traitement. Sa valeur par défaut est `false`. |
| `notification_suppression` | Non | Contrôle si les webhooks des opérations API sous-jacentes sont livrés. Définissez `{"scope": "all"}` pour supprimer les webhooks au niveau de l’opération. Les événements au niveau du lot sont toujours livrés quel que soit ce paramètre. Par défaut, `{"scope": "none"}`. |
| `metadata` | Non | Paires clé-valeur pour votre suivi interne. Les métadonnées sont incluses dans les événements de traitement par lots, y compris les événements d’échec. |

## Charger le fichier d’entrée

Après avoir créé le traitement par lots, chargez votre fichier d’entrée dans l’URL dans `status_details.ready_for_upload.upload_url.url`. Utilisez une requête `PUT` avec le contenu du fichier&nbsp;:

```bash
curl {UPLOAD_URL} \
  -X PUT \
  -T input.jsonl \
  -H "Content-Type: application/jsonlines"
```

Le fichier d’entrée pour cette requête doit être un fichier JSONL et le type de contenu doit être `application/jsonlines`. Une fois le chargement terminé, Stripe démarre automatiquement le traitement. Il n’y a pas d’étape `start` distincte.

> Une réponse&nbsp;`200` à la requête `PUT` provient du stockage (Amazon S3), qui accepte les octets bruts directement via l’URL présignée. Cela confirme uniquement que le chargement a réussi et que l’en-tête `Content-Type` est correct, mais ne signifie pas que Stripe a inspecté le fichier ou que le contenu a passé la validation.
> 
> La validation du corps du fichier (JSONL valide, champs obligatoires, etc.) s’exécute de manière asynchrone après le chargement. Lorsque `skip_validation` a la valeur `false`, la tâche passe à l’état `validating`, puis à `validation_failed` si le contenu est invalide.
> 
> Pour connaître le résultat, [interrogez la tâche par lot](https://docs.stripe.com/batch-api/create.md#monitor-job-status) (`GET /v2/core/batch_jobs/{BATCH_JOB_ID}`) et inspectez ses paramètres `status` et `status_details`.

L’URL de chargement expire 5 minutes après la création du traitement par lots. Vérifiez le champ `expires_at` pour connaître la date limite exacte. Si l’URL expire avant que vous ne chargiez le fichier, l’état du traitement passe à `upload_timeout`, et vous devez créer un nouveau traitement par lots. Générez le fichier d’entrée avant de créer le traitement par lots pour pouvoir le charger rapidement.

### Format du fichier d’entrée

Le fichier doit être encodé en UTF-8 et utiliser le format JSONL (JSON délimité par des sauts de ligne, un objet par ligne). Chaque ligne représente une requête API unique à l’endpoint cible. Le format CSV et les autres formats ne sont pas pris en charge.

Le fichier est limité à 2&nbsp;millions de lignes. Stripe compte les lignes une fois le chargement terminé, et les traitements qui dépassent la limite passent au statut `validation_failed` sans traiter aucune requête. Pour traiter plus de 2&nbsp;millions de lignes, divisez la charge de travail en plusieurs traitements par lots de 2&nbsp;millions de lignes maximum chacun et soumettez-les de manière séquentielle (attendez qu’un traitement se termine avant de créer le suivant). L’exécution simultanée de plusieurs traitements par lots volumineux peut être plus lente et moins fiable que l’exécution du même travail sous forme de traitements séquentiels. Si vous avez besoin d’une capacité supérieure, contactez le [service de support Stripe](https://support.stripe.com/contact).

Chaque objet JSON prend en charge les champs suivants&nbsp;:

| Champ | Obligatoire | Description |
| --- | --- | --- |
| `id` | Oui | Un identifiant unique pour corréler cette requête avec son résultat. Les identifiants des paramètres du chemin d’accès et les identifiants de l’endpoint doivent correspondre, bien que l’utilisateur soit libre de choisir comment les nommer&nbsp;: doivent correspondre à `/^[A-Za-z0-9_-]+$/`. |
| `path_params` | Conditionnel | Paramètres du chemin d’accès pour l’endpoint. Obligatoire lorsque le chemin d’accès de l’endpoint inclut des emplacements réservés (par exemple, `:id`). Les clés dans `path_params` doivent correspondre exactement aux emplacements réservés dans le chemin d’accès de l’endpoint. |
| `params` | Non | Paramètres du corps de la requête pour l’appel à l’API. Des variations peuvent se produire sur la base de la méthode de l’API. |
| `context` | Non | Un ID de compte Stripe. Utilisez-le pour exécuter la requête sur un compte spécifique, par exemple un compte connecté. |

### Exemple de fichier d’entrée

Each example uses JSONL format, with one complete JSON object per line, so you can copy it directly into an input file. To see the example for an endpoint, select its path from the **Endpoint** list.

#### Endpoint - /v1/accounts (POST)

Pour l’endpoint `POST /v1/accounts`&nbsp;:

```json
{"id": "req_001", "params": {"type": "custom", "country": "US", "capabilities": {"card_payments": {"requested": true}}}}
{"id": "req_002", "params": {"type": "custom", "country": "GB", "capabilities": {"card_payments": {"requested": true}}}}
```

#### Endpoint - /v1/accounts/:id (POST)

Pour le endpoint `POST /v1/accounts/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "acct_1AbCdEfGhIjKlMn"}, "params": {"business_type": "company", "company": {"name": "Updated Company Name"}}}
{"id": "req_002", "path_params": {"id": "acct_2BcDeFgHiJkLmNo"}, "params": {"business_type": "individual"}}
```

#### Endpoint - /v1/coupons (POST)

Pour l’endpoint `POST /v1/coupons`&nbsp;:

```json
{"id": "req_001", "params": {"percent_off": 25, "duration": "repeating", "duration_in_months": 3}}
{"id": "req_002", "context": "acct_1234567890", "params": {"amount_off": 500, "currency": "usd", "duration": "once", "name": "Summer Sale"}}
```

#### Endpoint - /v1/coupons/:coupon (POST)

Pour l’endpoint `POST /v1/coupons/:coupon`&nbsp;:

```json
{"id": "req_001", "path_params": {"coupon": "nVJYDOag"}, "params": {"name": "Summer Sale"}}
{"id": "req_002", "path_params": {"coupon": "Z4OV52SU"}, "params": {"metadata": {"campaign": "winter_2025"}}}
```

#### Endpoint - /v1/coupons/:coupon (DELETE)

Pour l’endpoint `DELETE /v1/coupons/:coupon`&nbsp;:

```json
{"id": "req_001", "path_params": {"coupon": "nVJYDOag"}}
{"id": "req_002", "path_params": {"coupon": "Z4OV52SU"}}
```

#### Endpoint - /v1/credit_notes (POST)

Pour le endpoint `POST /v1/credit_notes`&nbsp;:

```json
{"id": "req_001", "params": {"invoice": "in_1AbCdEfGhIjKlMn", "amount": 1000}}
{"id": "req_002", "params": {"invoice": "in_2BcDeFgHiJkLmNo", "amount": 500, "memo": "Service credit"}}
```

#### Endpoint - /v1/customers (POST)

Pour l’endpoint `POST /v1/customers`&nbsp;:

```json
{"id": "req_001", "params": {"email": "alice@example.com", "name": "Alice Smith"}}
{"id": "req_002", "params": {"email": "bob@example.com", "name": "Bob Jones", "phone": "+18005550123"}}
{"id": "req_003", "context": "acct_1234567890", "params": {"email": "carol@example.com", "name": "Carol White", "metadata": {"import_id": "legacy_001"}}}
```

#### Endpoint - /v1/customers/:customer/bank_accounts/:id (POST)

Pour l’endpoint `POST /v1/customers/:customer/bank_accounts/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"customer": "cus_1AbCdEfGhIjKlMn", "id": "ba_1AbCdEfGhIjKlMn"}, "params": {"account_holder_name": "Jane Doe"}}
{"id": "req_002", "path_params": {"customer": "cus_2BcDeFgHiJkLmNo", "id": "ba_2BcDeFgHiJkLmNo"}, "params": {"account_holder_name": "John Smith"}}
```

#### Endpoint - /v1/customers/:id (POST)

Pour le endpoint `POST /v1/customers/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "cus_1AbCdEfGhIjKlMn"}, "params": {"name": "Jenny Rosen", "email": "jenny@example.com"}}
{"id": "req_002", "path_params": {"id": "cus_2BcDeFgHiJkLmNo"}, "params": {"name": "John Smith", "metadata": {"tier": "premium"}}}
{"id": "req_003", "context": "acct_1234567890", "path_params": {"id": "cus_3CdEfGhIjKlMnOp"}, "params": {"description": "Updated by batch"}}
```

#### Endpoint - /v1/customers/:id (DELETE)

Pour l’endpoint `DELETE /v1/customers/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "cus_1AbCdEfGhIjKlMn"}, "params": {}}
{"id": "req_002", "path_params": {"id": "cus_2BcDeFgHiJkLmNo"}, "params": {}}
```

#### Endpoint - /v1/disputes/:dispute/close (POST)

Pour l’endpoint `POST /v1/disputes/:dispute/close`&nbsp;:

```json
{"id": "req_001", "path_params": {"dispute": "dp_1AbCdEfGhIjKlMn"}}
{"id": "req_002", "path_params": {"dispute": "dp_2BcDeFgHiJkLmNo"}}
```

#### Endpoint - /v1/entitlements/features (POST)

Pour l’endpoint `POST /v1/entitlements/features`&nbsp;:

```json
{"id": "req_001", "params": {"name": "Premium Access", "lookup_key": "premium_access"}}
{"id": "req_002", "params": {"name": "Advanced Analytics", "lookup_key": "advanced_analytics"}}
```

#### Endpoint - /v1/entitlements/features/:id (POST)

Pour l’endpoint `POST /v1/entitlements/features/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "feat_1AbCdEfGhIjKlMn"}, "params": {"name": "Updated Feature Name"}}
{"id": "req_002", "path_params": {"id": "feat_2BcDeFgHiJkLmNo"}, "params": {"active": false}}
```

#### Endpoint - /v1/invoiceitems (POST)

Pour l’endpoint `POST /v1/invoiceitems`&nbsp;:

```json
{"id": "req_001", "params": {"customer": "cus_1AbCdEfGhIjKlMn", "amount": 1000, "currency": "usd", "description": "Consulting fee"}}
{"id": "req_002", "params": {"customer": "cus_2BcDeFgHiJkLmNo", "amount": 2500, "currency": "usd", "description": "Platform fee"}}
```

#### Endpoint - /v1/invoiceitems/:id (POST)

Pour l’endpoint `POST /v1/invoiceitems/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "ii_1AbCdEfGhIjKlMn"}, "params": {"description": "Updated consulting fee"}}
{"id": "req_002", "path_params": {"id": "ii_2BcDeFgHiJkLmNo"}, "params": {"amount": 3000}}
```

#### Endpoint - /v1/invoiceitems/:id (DELETE)

Pour l’endpoint `DELETE /v1/invoiceitems/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "ii_1AbCdEfGhIjKlMn"}}
{"id": "req_002", "path_params": {"id": "ii_2BcDeFgHiJkLmNo"}}
```

#### Endpoint - /v1/invoices/:id (POST)

Pour le endpoint `POST /v1/invoices/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "in_1AbCdEfGhIjKlMn"}, "params": {"collection_method": "send_invoice", "days_until_due": 30}}
{"id": "req_002", "path_params": {"id": "in_2BcDeFgHiJkLmNo"}, "params": {"description": "Updated invoice description"}}
```

#### Endpoint - /v1/invoices/:invoice/add_lines (POST)

Pour l’endpoint `POST /v1/invoices/:invoice/add_lines`&nbsp;:

```json
{"id": "req_001", "path_params": {"invoice": "in_1AbCdEfGhIjKlMn"}, "params": {"lines": [{"amount": 1000, "description": "Consulting services"}]}}
{"id": "req_002", "path_params": {"invoice": "in_2BcDeFgHiJkLmNo"}, "params": {"lines": [{"amount": 2500, "description": "Platform fee"}]}}
```

#### Endpoint - /v1/plans (POST)

Pour l’endpoint `POST /v1/plans`&nbsp;:

```json
{"id": "req_001", "params": {"amount": 1000, "currency": "usd", "interval": "month", "product": "prod_1AbCdEfGhIjKlMn"}}
{"id": "req_002", "params": {"amount": 2500, "currency": "usd", "interval": "year", "product": "prod_2BcDeFgHiJkLmNo"}}
```

#### Endpoint - /v1/plans/:id (POST)

Pour l’endpoint `POST /v1/plans/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "plan_1AbCdEfGhIjKlMn"}, "params": {"nickname": "Monthly standard"}}
{"id": "req_002", "path_params": {"id": "plan_2BcDeFgHiJkLmNo"}, "params": {"active": "false"}}
```

#### Endpoint - /v1/plans/:id (DELETE)

Pour l’endpoint `DELETE /v1/plans/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "plan_1AbCdEfGhIjKlMn"}}
{"id": "req_002", "path_params": {"id": "plan_2BcDeFgHiJkLmNo"}}
```

#### Endpoint - /v1/prices/:id (POST)

Pour l’endpoint `POST /v1/prices/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "price_1AbCdEfGhIjKlMn"}, "params": {"active": false}}
{"id": "req_002", "path_params": {"id": "price_2BcDeFgHiJkLmNo"}, "params": {"metadata": {"tier": "premium"}}}
```

#### Endpoint - /v1/products (POST)

Pour l’endpoint `POST /v1/products`&nbsp;:

```json
{"id": "req_001", "params": {"name": "Premium Widget"}}
{"id": "req_002", "context": "acct_1234567890", "params": {"name": "Basic Widget", "description": "An affordable widget", "metadata": {"category": "widgets"}}}
```

#### Endpoint - /v1/products/:id (POST)

Pour l’endpoint `POST /v1/products/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "prod_1AbCdEfGhIjKlMn"}, "params": {"name": "Updated Product Name", "description": "New description"}}
{"id": "req_002", "path_params": {"id": "prod_2BcDeFgHiJkLmNo"}, "params": {"active": false}}
```

#### Endpoint - /v1/products/:id (DELETE)

Pour l’endpoint `DELETE /v1/products/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "prod_1AbCdEfGhIjKlMn"}}
{"id": "req_002", "path_params": {"id": "prod_2BcDeFgHiJkLmNo"}}
```

#### Endpoint - /v1/products/:product/features (POST)

Pour l’endpoint `POST /v1/products/:product/features`&nbsp;:

```json
{"id": "req_001", "path_params": {"product": "prod_1AbCdEfGhIjKlMn"}, "params": {"entitlement_feature": "feat_1AbCdEfGhIjKlMn"}}
{"id": "req_002", "path_params": {"product": "prod_2BcDeFgHiJkLmNo"}, "params": {"entitlement_feature": "feat_2BcDeFgHiJkLmNo"}}
```

#### Endpoint - /v1/products/:product/features/:id (DELETE)

Pour l’endpoint `DELETE /v1/products/:product/features/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"product": "prod_1AbCdEfGhIjKlMn", "id": "prodft_1AbCdEfGhIjKlMn"}}
{"id": "req_002", "path_params": {"product": "prod_2BcDeFgHiJkLmNo", "id": "prodft_2BcDeFgHiJkLmNo"}}
```

#### Endpoint - /v1/promotion_codes (POST)

Pour le endpoint `POST /v1/promotion_codes`&nbsp;:

```json
{"id": "req_001", "params": {"promotion": {"type": "coupon", "coupon": "nVJYDOag"}, "code": "SUMMER25"}}
{"id": "req_002", "params": {"promotion": {"type": "coupon", "coupon": "Z4OV52SU"}, "code": "WINTER50", "max_redemptions": 100}}
```

#### Endpoint - /v1/promotion_codes/:id (POST)

Pour le endpoint `POST /v1/promotion_codes/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "promo_1AbCdEfGhIjKlMn"}, "params": {"active": false}}
{"id": "req_002", "path_params": {"id": "promo_2BcDeFgHiJkLmNo"}, "params": {"metadata": {"tier": "premium"}}}
```

#### Endpoint - /v1/radar/value_list_items (POST)

Pour l’endpoint `POST /v1/radar/value_list_items`&nbsp;:

```json
{"id": "req_001", "params": {"value_list": "rsl_1AbCdEfGhIjKlMn", "value": "1.2.3.4"}}
{"id": "req_002", "params": {"value_list": "rsl_1AbCdEfGhIjKlMn", "value": "5.6.7.8"}}
```

#### Endpoint - /v1/subscription_items/:item (POST)

Pour l’endpoint `POST /v1/subscription_items/:item`&nbsp;:

```json
{"id": "req_001", "path_params": {"item": "si_1AbCdEfGhIjKlMn"}, "params": {"price": "price_1AbCdEfGhIjKlMn", "quantity": 5}}
{"id": "req_002", "path_params": {"item": "si_2BcDeFgHiJkLmNo"}, "params": {"price": "price_2BcDeFgHiJkLmNo"}}
```

#### Endpoint - /v1/subscription_items/:item (DELETE)

Pour l’endpoint `DELETE /v1/subscription_items/:item`&nbsp;:

```json
{"id": "req_001", "path_params": {"item": "si_1AbCdEfGhIjKlMn"}}
{"id": "req_002", "path_params": {"item": "si_2BcDeFgHiJkLmNo"}, "params": {"clear_usage": true}}
```

#### Endpoint - /v1/subscription_schedules (POST)

Pour le endpoint `POST /v1/subscription_schedules`&nbsp;:

```json
{"id": "req_001", "params": {"customer": "cus_1AbCdEfGhIjKlMn", "start_date": 1640995200, "phases": [{"items": [{"price": "price_1AbCdEfGhIjKlMn", "quantity": 1}], "iterations": 12}]}}
{"id": "req_002", "params": {"customer": "cus_2BcDeFgHiJkLmNo", "start_date": 1640995200, "phases": [{"items": [{"price": "price_2BcDeFgHiJkLmNo", "quantity": 2}], "iterations": 6}]}}
```

#### Endpoint - /v1/subscription_schedules/:id (POST)

Pour le endpoint `POST /v1/subscription_schedules/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "sub_sched_1AbCdEfGhIjKlMn"}, "params": {"end_behavior": "cancel"}}
{"id": "req_002", "path_params": {"id": "sub_sched_2BcDeFgHiJkLmNo"}, "params": {"end_behavior": "release"}}
```

#### Endpoint - /v1/subscription_schedules/:id/cancel (POST)

Pour le endpoint `POST /v1/subscription_schedules/:id/cancel`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "sub_sched_1AbCdEfGhIjKlMn"}}
{"id": "req_002", "path_params": {"id": "sub_sched_2BcDeFgHiJkLmNo"}}
```

#### Endpoint - /v1/subscription_schedules/:schedule/release (POST)

Pour l’endpoint `POST /v1/subscription_schedules/:schedule/release`&nbsp;:

```json
{"id": "req_001", "path_params": {"schedule": "sub_sched_1AbCdEfGhIjKlMn"}, "params": {}}
{"id": "req_002", "path_params": {"schedule": "sub_sched_2BcDeFgHiJkLmNo"}, "params": {"preserve_cancel_date": true}}
```

#### Endpoint - /v1/subscriptions (POST)

Pour l’endpoint `POST /v1/subscriptions`&nbsp;:

```json
{"id": "req_001", "params": {"customer": "cus_1AbCdEfGhIjKlMn", "items": [{"price": "price_1AbCdEfGhIjKlMn"}]}}
{"id": "req_002", "params": {"customer": "cus_2BcDeFgHiJkLmNo", "items": [{"price": "price_2BcDeFgHiJkLmNo", "quantity": 3}]}}
```

#### Endpoint - /v1/subscriptions/:id (POST)

Pour le endpoint `POST /v1/subscriptions/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "sub_1AbCdEfGhIjKlMn"}, "params": {"description": "Updated subscription description"}}
{"id": "req_002", "path_params": {"id": "sub_2BcDeFgHiJkLmNo"}, "params": {"metadata": {"migration_batch": "v2"}}}
{"id": "req_003", "context": "acct_1234567890", "path_params": {"id": "sub_3CdEfGhIjKlMnOp"}, "params": {"cancel_at_period_end": true}}
```

#### Endpoint - /v1/subscriptions/:id (DELETE)

Pour l’endpoint `DELETE /v1/subscriptions/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "sub_1AbCdEfGhIjKlMn"}}
{"id": "req_002", "path_params": {"id": "sub_2BcDeFgHiJkLmNo"}, "params": {"cancellation_details": {"comment": "Customer requested cancellation"}}}
```

#### Endpoint - /v1/subscriptions/:id/migrate (POST)

Pour le endpoint `POST /v1/Subscriptions/:id/migrate`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "sub_1AbCdEfGhIjKlMn"}, "params": {"billing_mode": {"type": "flexible"}}}
{"id": "req_002", "context": "acct_1234567890", "path_params": {"id": "sub_2BcDeFgHiJkLmNo"}, "params": {"billing_mode": {"type": "flexible", "flexible": {"proration_discounts": "included"}}}}
```

#### Endpoint - /v1/tax/registrations (POST)

Pour l’endpoint `POST /v1/tax/registrations`&nbsp;:

```json
{"id": "req_001", "params": {"country": "IE", "country_options": {"ie": {"type": "standard"}}, "active_from": "now"}}
{"id": "req_002", "params": {"country": "DE", "country_options": {"de": {"type": "standard"}}, "active_from": "now"}}
```

#### Endpoint - /v1/tax/registrations/:id (POST)

Pour l’endpoint `POST /v1/tax/registrations/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "taxreg_1abc"}, "params": {"expires_at": 1735689600}}
{"id": "req_002", "path_params": {"id": "taxreg_2def"}, "params": {"expires_at": 1735689600}}
```

#### Endpoint - /v1/tax/settings (POST)

Pour l’endpoint `POST /v1/tax/settings`&nbsp;:

```json
{"id": "req_001", "params": {"defaults": {"tax_code": "txcd_10000000"}}}
```

#### Endpoint - /v1/tax_rates/:id (POST)

Pour l’endpoint `POST /v1/tax_rates/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "txr_1abc"}, "params": {"active": false}}
{"id": "req_002", "path_params": {"id": "txr_2def"}, "params": {"display_name": "Updated Tax"}}
```

#### Endpoint - /v1/transfers (POST)

Pour l’endpoint `POST /v1/transfers`&nbsp;:

```json
{"id": "req_001", "params": {"destination": "acct_1AbCdEfGhIjKlMn", "currency": "usd", "amount": 1000}}
{"id": "req_002", "params": {"destination": "acct_2BcDeFgHiJkLmNo", "currency": "usd", "amount": 2500}}
```

#### Endpoint - /v1/transfers/:id (POST)

Pour l’endpoint `POST /v1/transfers/:id`&nbsp;:

```json
{"id": "req_001", "path_params": {"id": "tr_1AbCdEfGhIjKlMn"}, "params": {"description": "Updated transfer description"}}
{"id": "req_002", "path_params": {"id": "tr_2BcDeFgHiJkLmNo"}, "params": {"metadata": {"order_id": "6735"}}}
```

Chaque `id` doit être unique dans le fichier. Stripe l’utilise pour corréler les requêtes avec les résultats, car le fichier des résultats n’est pas ordonné de la même manière que le fichier d’entrée.

## Suivre l’état du traitement

Vous pouvez suivre votre traitement par lots en interrogeant l’endpoint de récupération ou en écoutant les [événements webhook](https://docs.stripe.com/batch-api/create.md#webhook-events). Nous vous recommandons d’utiliser des événements webhook pour les intégrations en production.

### Vérifier l’état par interrogation de l’API

```curl
curl https://api.stripe.com/v2/core/batch_jobs/batchv2_AbCdEfGhIjKlMnOpQrStUvWxYz \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-09-30.preview"
```

Le type de contenu de cette requête est un fichier json. Pendant que la tâche est en cours d’exécution, `status_details` inclut des décomptes de progression en temps réel&nbsp;:

```json
{
  "status": "in_progress",
  "status_details": {
    "in_progress": {
      "success_count": "1",
      "failure_count": "0"
    }
  }
}
```

Pendant la phase `validating`, `status_details` inclut un champ `validated_count` qui indique le nombre de lignes validées par Stripe jusqu’à présent.

Les appels à l’API Batch Job apparaissent dans les logs de requêtes Stripe Dashboard ou Workbench. Les appels à l’API sous-jacents n’apparaissent pas dans les logs de requêtes. Utilisez l’endpoint de récupération ou les événements webhook pour suivre la progression. Pour déboguer les échecs de requêtes individuelles, consultez le fichier de résultats.

### Cycle de vie du traitement

Une fois que vous avez chargé le fichier d’entrée, le traitement par lots passe par les états suivants&nbsp;:

| État | Description |
| --- | --- |
| `ready_for_upload` | Le traitement par lots lot a été créé et attend le fichier d’entrée. |
| `validating` | Stripe a accepté le fichier chargé et le valide. Ignoré lorsque `skip_validation` est défini sur `true`. |
| `in_progress` | La validation a réussi (ou a été ignorée) et Stripe traite les requêtes. |
| `complete` | Toutes les demandes ont été traitées. Les résultats sont téléchargeables. |
| `cancelling` | Une annulation a été demandée. Stripe finalise les requêtes en cours. |

### États Terminal

| État | Description |
| --- | --- |
| `validation_failed` | Le fichier d’entrée contient des erreurs. Aucune requête n’a été traitée. Vérifiez les détails de l’erreur dans l’objet du traitement par lots. Cela ne s’applique que lorsque `skip_validation: false`. |
| `batch_failed` | Une erreur inattendue s’est produite lors du traitement. |
| `cancelled` | Le traitement par lots a été annulé. Des résultats partiels peuvent être disponibles. |
| `upload_timeout` | L’URL de chargement a expiré avant le chargement du fichier. Créez un nouveau traitement par lots. |
| `timeout` | La tâche par lots a dépassé la durée maximale de traitement de 7&nbsp;jours. Des résultats partiels peuvent être disponibles. |

### Validation

When `skip_validation` is `false` (the default), Stripe validates the entire input file before processing any requests. This validation catches errors such as:

- Invalid JSON on any line
- Missing or invalid `id` fields
- Duplicate IDs
- Missing required `path_params` for the target endpoint

For `/v1` endpoints, validation also checks the parameters in each request, so unknown parameters and invalid parameter values fail validation. Errors that depend on the state of the objects you reference, such as migrating a subscription that isn’t active, only appear when Stripe executes the request. These failures appear in the results file with a non-`200` status. To catch them before you run a large batch, [test your input with a small batch](https://docs.stripe.com/batch-api/best-practices.md#test-with-a-small-batch-first) first.

Si la validation échoue, l’état passe à `validation_failed`, et Stripe ne tente aucune requête. L’objet traitement par lots inclut des détails de la première erreur qu’il rencontre.

Lorsque `skip_validation` est `true`, la tâche passe directement de `ready_for_upload` à `in_progress` après le chargement. Les erreurs dans les requêtes individuelles apparaissent dans le fichier des résultats au lieu de bloquer l’ensemble du lot.

### Événements webhook

Les traitements par lots émettent des événements légers&nbsp;v2 pour chaque transition du cycle de vie. Pour recevoir ces événements, vous devez configurer une [destination d’événement&nbsp;v2](https://docs.stripe.com/events/set-up-events.md).

Les événements de traitements par lots nécessitent des destinations d’événement v2. Ils ne sont pas envoyés aux endpoints webhook v1.

Les événements suivants sont disponibles&nbsp;:

| Type d’événement | Description |
| --- | --- |
| `v2.core.batch_job.created` | Un traitement par lots a été créé. |
| `v2.core.batch_job.ready_for_upload` | Le traitement par lots est prêt pour le chargement de fichiers. |
| `v2.core.batch_job.validating` | Chargement du fichier terminé, validation en cours. |
| `v2.core.batch_job.validation_failed` | La validation du fichier d’entrée a échoué. |
| `v2.core.batch_job.completed` | Toutes les requêtes ont été traitées. |
| `v2.core.batch_job.batch_failed` | Le traitement par lots a échoué de manière inattendue. |
| `v2.core.batch_job.canceled` | Le traitement par lots a été annulé. |
| `v2.core.batch_job.timeout` | Le traitement par lots a dépassé la durée maximale de traitement. |
| `v2.core.batch_job.upload_timeout` | L’URL de chargement a expiré avant le chargement du fichier. |
| `v2.core.batch_job.updated` | L’état ou la progression du traitement par lots a changé. |

Tous les événements du traitement par lots incluent les métadonnées que vous avez fournies lors de la création du traitement. Utilisez-les pour corréler les événements avec vos systèmes internes.

Lorsque `notification_suppression` est défini sur `{"scope": "all"}`, les webhooks des opérations API sous-jacentes (par exemple, les événements de mise à jour d’abonnement) sont supprimés. Les événements de niveau lot listés ci-dessus sont toujours livrés quel que soit ce paramètre.

## Télécharger les résultats

Lorsque le traitement par lots atteint l’état `complete`, le champ `status_details` inclut un récapitulatif des réussites et des échecs, ainsi qu’une URL de téléchargement présignée pour le fichier de sortie&nbsp;:

```json
{
  "id": "batchv2_AbCdEfGhIjKlMnOpQrStUvWxYz",
  "object": "v2.core.batch_job",
  "created": "2026-03-09T20:55:31.000Z",
  "skip_validation": true,
  "status": "complete",
  "status_details": {
    "complete": {
      "success_count": "2",
      "failure_count": "0",
      "output_file": {
        "content_type": "application/jsonlines",
        "size": "8514",
        "download_url": {
          "expires_at": "2026-03-09T22:05:31.000Z",
          "url": "https://stripeusercontent.com/files/download/..."
        }
      }
    }
  }
}
```

Téléchargez le fichier en utilisant l’URL dans `status_details.complete.output_file.download_url.url`. Stripe fournit un fichier de sortie lorsque le traitement par lots atteint l’un des états suivants&nbsp;:

- `complete`
- `cancelled`
- `timeout`
- `validation_failed`

Pour savoir quand l’URL de téléchargement expire, vérifiez le champ `expires_at` correspondant à la date limite.

Le fichier des résultats contient les requêtes réussies et échouées dans un seul fichier. Pour trouver les échecs, filtrez les lignes dont `status` n’est pas `200`.

### Format du fichier des résultats

Le fichier de sortie utilise le format JSONL (un objet JSON par ligne). Chaque ligne contient les champs suivants&nbsp;:

| Champ | Description |
| --- | --- |
| `id` | L’ID de requête du fichier d’entrée. Utilisez-le pour corréler les résultats avec les requêtes. |
| `response` | L’objet API response complet. Contient la ressource en cas de réussite, ou un objet error en cas d’échec. |
| `status` | Le code d’état HTTP sous forme de nombre entier (par exemple, `200`, `402`). |
| `context` | Le compte connecté sur lequel la requête a été exécutée. |

### Exemple de fichier de résultats

Les requêtes réussies renvoient la ressource API complète dans le champ `response`&nbsp;:

```json
{
  "id": "req_001",
  "response": {
    "id": "sub_1AbCdEfGhIjKlMn",
    "object": "subscription",
    "status": "active",
    "billing_cycle_anchor": 1710021331,
    "current_period_end": 1712613331,
    "current_period_start": 1710021331
  },
  "status": 200
}
{
  "id": "req_002",
  "response": {
    "id": "sub_2BcDeFgHiJkLmNo",
    "object": "subscription",
    "status": "active",
    "billing_cycle_anchor": 1710021331,
    "current_period_end": 1712613331,
    "current_period_start": 1710021331
  },
  "status": 200
}
```

Les requêtes échouées renvoient un objet error&nbsp;:

```json
{
  "id": "req_003",
  "response": {
    "error": {
      "message": "This subscription cannot be migrated because it is not active. Current status is canceled.",
      "type": "invalid_request_error",
      "code": "resource_invalid_state"
    }
  },
  "status": 400
}
```

Lorsqu’une ligne d’entrée inclut un `context`, la sortie correspondante l’inclut&nbsp;:

```json
{
  "id": "req_001",
  "context": "acct_1234567890",
  "response": {
    "id": "sub_1AbCdEfGhIjKlMn",
    "object": "subscription",
    "status": "active"
  },
  "status": 200
}
```

> Stripe doesn’t process requests in input order, and the results file doesn’t follow the order of the input file. Results from a small test file might appear in order, but don’t rely on that for any file size. Always use the `id` field to match each result to its request.

## Create related objects across batches

Each request in a batch runs independently, so a request can’t reference an object that another request in the same batch creates. To create related objects, such as customers and their subscriptions, run a separate batch job for each step:

1. Create a batch job for the first endpoint (for example, `POST /v1/customers`). Give each line an `id` that identifies the record in your system.

   ```json
   {"id": "user_001", "params": {"email": "alice@example.com"}}
   {"id": "user_002", "params": {"email": "bob@example.com"}}
   ```

2. When the first job finishes, download the results file and map each `id` to the Stripe object ID in `response.id`. Leave lines where the `status` field isn’t `200` out of the next batch, and handle those failures separately.

3. Create a second batch job for the next endpoint (for example, `POST /v1/subscriptions`) and use the customer IDs from the first results file in each line.

   ```json
   {"id": "user_001", "params": {"customer": "cus_1AbCdEfGhIjKlMn", "items": [{"price": "price_1AbCdEfGhIjKlMn"}]}}
   {"id": "user_002", "params": {"customer": "cus_2BcDeFgHiJkLmNo", "items": [{"price": "price_1AbCdEfGhIjKlMn"}]}}
   ```

Wait for each job to finish before you create the next one. Because results aren’t ordered, always build the mapping from the `id` field, not from the line position.

## Annuler un traitement par lot

Vous pouvez annuler un traitement par lots qui n’est pas encore terminé en envoyant une requête `POST`&nbsp;:

```curl
curl -X POST https://api.stripe.com/v2/core/batch_jobs/batchv2_AbCdEfGhIjKlMnOpQrStUvWxYz/cancel \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-09-30.preview"
```

L’annulation est asynchrone. La tâche par lots passe d’abord à l’état `cancelling` pendant que les requêtes en cours se terminent, puis à l’état `cancelled`. Les résultats partiels des requêtes traitées avant l’annulation sont disponibles dans le fichier de résultats.

## Utilisation avec Connect

Les comptes de plateforme peuvent exécuter des traitements par lots au nom de comptes connectés. Créez le traitement par lots à l’aide de la clé d’API de votre plateforme comme d’habitude. Afin de cibler un compte connecté pour des requêtes individuelles dans le fichier d’entrée, définissez le champ `context` sur l’ID du compte connecté. Il s’agit de l’équivalent par requête de l’en-tête `Stripe-Account` dans les appels d’API directs.

```curl
curl -X POST https://api.stripe.com/v2/core/batch_jobs \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-09-30.preview" \
  --json '{
    "endpoint": {
        "path": "/v1/subscriptions/:id/migrate",
        "http_method": "post"
    }
  }'
```

Dans le fichier d’entrée, ajoutez `context` à chaque ligne devant être exécutée en tant que compte connecté&nbsp;:

```json
{"id": "req_001", "context": "acct_1AbCdEfGhIjKlMn", "path_params": {"id": "sub_1AbCdEfGhIjKlMn"}, "params": {"billing_cycle_anchor": "unchanged"}}
{"id": "req_002", "context": "acct_2BcDeFgHiJkLmNo", "path_params": {"id": "sub_2BcDeFgHiJkLmNo"}, "params": {"billing_cycle_anchor": "unchanged"}}
{"id": "req_003", "path_params": {"id": "sub_3CdEfGhIjKlMnOp"}, "params": {"billing_cycle_anchor": "unchanged"}}
```

Les lignes sans `context` sont exécutées en tant que compte de plateforme. Les lignes avec `context` sont exécutées en tant que compte connecté spécifié. Vous pouvez combiner les deux dans le même fichier de traitement par lots.
