# Faire pivoter des pages d’un PDF

Faites pivoter les pages sélectionnées d’un PDF d’un angle fixe, dans le sens horaire ou antihoraire.

Faites pivoter les pages d’un document PDF d’un angle fixe. Les angles positifs
font pivoter dans le sens horaire, les angles négatifs dans le sens antihoraire.
Par défaut, toutes les pages pivotent : utilisez le paramètre
[`pages`](#sélectionner-des-pages) pour n’en viser qu’une partie. L’API est
*stateless* : votre document est traité dans la région et n’est jamais stocké.

## Endpoint

<Endpoint method="POST" path="/v1/rotate_pages" />

Disponible dans toutes les régions. Consultez [Régions et résidence des
données](/docs/api/regions-and-data-residency) pour le routage et la résidence
des données.

| Région           | URL                                               |
| ---------------- | ------------------------------------------------- |
| Global           | `https://api.pdfblocks.com/v1/rotate_pages`       |
| États-Unis       | `https://us.api.pdfblocks.com/v1/rotate_pages`    |
| HIPAA États-Unis | `https://hipaa.api.pdfblocks.com/v1/rotate_pages` |
| Union européenne | `https://eu.api.pdfblocks.com/v1/rotate_pages`    |
| Royaume-Uni      | `https://uk.api.pdfblocks.com/v1/rotate_pages`    |
| Canada           | `https://ca.api.pdfblocks.com/v1/rotate_pages`    |
| Australie        | `https://au.api.pdfblocks.com/v1/rotate_pages`    |
| Japon            | `https://jp.api.pdfblocks.com/v1/rotate_pages`    |
| Inde             | `https://in.api.pdfblocks.com/v1/rotate_pages`    |
| Brésil           | `https://br.api.pdfblocks.com/v1/rotate_pages`    |

## Authentification

Authentifiez chaque requête avec votre clé d’API secrète dans l’en-tête
`X-API-Key`, via HTTPS. Créez et gérez vos clés depuis le
[dashboard](https://dashboard.pdfblocks.com). Consultez
[Authentification](/docs/api/authentication) pour plus de détails.

## Requête

L’endpoint accepte un corps de requête `multipart/form-data`.

<ParamField name="file" type="file" required>
  Le document PDF d’entrée.
</ParamField>

<ParamField name="angle" type="integer" required>
  La rotation à appliquer, en degrés. L’un des [angles
  valides](#angles-de-rotation). Les valeurs positives font pivoter dans le sens
  horaire, les valeurs négatives dans le sens antihoraire.
</ParamField>

<ParamField name="pages" type="string">
  Les pages à faire pivoter, écrites sous forme de [plage de
  pages](#sélectionner-des-pages), par exemple `1..3,5`. En cas d’omission,
  toutes les pages pivotent. Maximum 1000 caractères.
</ParamField>

### Angles de rotation

Passez au paramètre `angle` l’une des valeurs suivantes.

| Angle   | Rotation                                                 |
| ------- | -------------------------------------------------------- |
| `0`     | Aucune rotation                                          |
| `90`    | 90° dans le sens horaire                                 |
| `180`   | 180°                                                     |
| `270`   | 270° dans le sens horaire (90° dans le sens antihoraire) |
| `-90`   | 90° dans le sens antihoraire                             |
| `-180`  | 180°                                                     |
| `-270`  | 270° dans le sens antihoraire (90° dans le sens horaire) |

Les angles positifs font pivoter dans le sens horaire, les angles négatifs dans
le sens antihoraire ; chaque rotation s’ajoute à la rotation actuelle de la
page.

### Sélectionner des pages

Le paramètre `pages` prend une liste de numéros de page et de plages séparés par
des virgules, numérotés à partir de 1. Il est traité comme un **ensemble** :
l’ordre et les doublons sont ignorés, et les pages pivotent toujours dans
l’ordre du document.

| Motif       | Sélectionne                            |
| ----------- | -------------------------------------- |
| *(omettre)* | Toutes les pages                       |
| `1`         | La première page uniquement            |
| `1..3,5`    | Les pages 1, 2, 3 et 5                 |
| `2..`       | De la page 2 à la dernière             |
| `..-2`      | De la première page à l’avant-dernière |
| `-1`        | La dernière page                       |

Consultez [Sélectionner des pages](/docs/api/selecting-pages) pour la référence
complète.

## Exemples

Faites pivoter les trois premières pages de 90° dans le sens horaire :

<CodeGroup>

```bash title="cURL"
curl https://api.pdfblocks.com/v1/rotate_pages \
  -H 'X-API-Key: your_api_key' \
  -F file=@input.pdf \
  -F angle=90 \
  -F pages='1..3' \
  -o rotated.pdf
```

```python title="Python"
# pip install requests
import requests

with open('input.pdf', 'rb') as file:
    response = requests.post(
        'https://api.pdfblocks.com/v1/rotate_pages',
        headers={'X-API-Key': 'your_api_key'},
        files={'file': file},
        data={
            'angle': 90,
            'pages': '1..3',
        },
    )

response.raise_for_status()
with open('rotated.pdf', 'wb') as output:
    output.write(response.content)
```

```javascript title="Node.js"
// Node.js 18+
import { readFile, writeFile } from 'node:fs/promises';

const body = new FormData();
body.set('file', new Blob([await readFile('input.pdf')]), 'input.pdf');
body.set('angle', '90');
body.set('pages', '1..3');

const response = await fetch('https://api.pdfblocks.com/v1/rotate_pages', {
  method: 'POST',
  headers: { 'X-API-Key': 'your_api_key' },
  body,
});

if (!response.ok) throw new Error(`Request failed: ${response.status}`);
await writeFile('rotated.pdf', Buffer.from(await response.arrayBuffer()));
```

```php title="PHP"
<?php
$ch = curl_init('https://api.pdfblocks.com/v1/rotate_pages');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: your_api_key'],
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('input.pdf', 'application/pdf'),
        'angle' => '90',
        'pages' => '1..3',
    ],
]);

$pdf = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200) {
    file_put_contents('rotated.pdf', $pdf);
}
```

```ruby title="Ruby"
# gem install http
require 'http'

response = HTTP
  .headers('X-API-Key' => 'your_api_key')
  .post('https://api.pdfblocks.com/v1/rotate_pages', form: {
    file: HTTP::FormData::File.new('input.pdf'),
    angle: '90',
    pages: '1..3',
  })

File.write('rotated.pdf', response.body) if response.status.success?
```

```go title="Go"
package main

import (
	"bytes"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

func main() {
	var buf bytes.Buffer
	form := multipart.NewWriter(&buf)

	file, _ := os.Open("input.pdf")
	defer file.Close()
	part, _ := form.CreateFormFile("file", "input.pdf")
	io.Copy(part, file)

	form.WriteField("angle", "90")
	form.WriteField("pages", "1..3")
	form.Close()

	req, _ := http.NewRequest("POST", "https://api.pdfblocks.com/v1/rotate_pages", &buf)
	req.Header.Set("Content-Type", form.FormDataContentType())
	req.Header.Set("X-API-Key", "your_api_key")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()

	out, _ := os.Create("rotated.pdf")
	defer out.Close()
	io.Copy(out, res.Body)
}
```

```csharp title="C#"
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "your_api_key");

using var form = new MultipartFormDataContent
{
    { new ByteArrayContent(File.ReadAllBytes("input.pdf")), "file", "input.pdf" },
    { new StringContent("90"), "angle" },
    { new StringContent("1..3"), "pages" },
};

var response = await client.PostAsync(
    "https://api.pdfblocks.com/v1/rotate_pages", form);
response.EnsureSuccessStatusCode();
await File.WriteAllBytesAsync(
    "rotated.pdf", await response.Content.ReadAsByteArrayAsync());
```

</CodeGroup>

## Réponse

En cas de succès, la réponse est `200 OK` et le PDF pivoté constitue le corps :

```http
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Length: 48213
```

La sortie conserve les mêmes pages et le même contenu que l’entrée : seule la
rotation des pages sélectionnées change. Écrivez le corps directement dans un
fichier, comme le font les exemples ci-dessus ; rien n’est stocké de notre côté.

## Erreurs

Les requêtes en échec renvoient un corps `application/problem+json`. L’erreur la
plus fréquente sur cet endpoint est un `400`, renvoyé lorsque `angle` n’est pas
l’une des valeurs prises en charge ou que `file` n’est pas un PDF lisible :
l’objet `errors` nomme chaque champ :

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/400",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "angle": ["The angle must be one of 0, 90, 180, 270, -90, -180, -270."]
  }
}
```

Une `X-API-Key` absente ou non valide renvoie un `401`. Consultez
[Erreurs](/docs/api/errors) pour tous les codes de statut et la forme complète
de la réponse.

## Recettes

Variantes courantes. Dépliez-en une pour la voir dans tous les langages.

<AccordionGroup>

<Accordion title="Redresser un scan en paysage">

<CodeGroup>

```bash title="cURL"
curl https://api.pdfblocks.com/v1/rotate_pages \
  -H 'X-API-Key: your_api_key' \
  -F file=@input.pdf \
  -F angle=90 \
  -o upright.pdf
```

```python title="Python"
import requests

with open('input.pdf', 'rb') as file:
    response = requests.post(
        'https://api.pdfblocks.com/v1/rotate_pages',
        headers={'X-API-Key': 'your_api_key'},
        files={'file': file},
        data={'angle': 90},
    )

response.raise_for_status()
with open('upright.pdf', 'wb') as output:
    output.write(response.content)
```

```javascript title="Node.js"
import { readFile, writeFile } from 'node:fs/promises';

const body = new FormData();
body.set('file', new Blob([await readFile('input.pdf')]), 'input.pdf');
body.set('angle', '90');

const response = await fetch('https://api.pdfblocks.com/v1/rotate_pages', {
  method: 'POST',
  headers: { 'X-API-Key': 'your_api_key' },
  body,
});

if (!response.ok) throw new Error(`Request failed: ${response.status}`);
await writeFile('upright.pdf', Buffer.from(await response.arrayBuffer()));
```

```php title="PHP"
<?php
$ch = curl_init('https://api.pdfblocks.com/v1/rotate_pages');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: your_api_key'],
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('input.pdf', 'application/pdf'),
        'angle' => '90',
    ],
]);

$pdf = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200) {
    file_put_contents('upright.pdf', $pdf);
}
```

```ruby title="Ruby"
require 'http'

response = HTTP
  .headers('X-API-Key' => 'your_api_key')
  .post('https://api.pdfblocks.com/v1/rotate_pages', form: {
    file: HTTP::FormData::File.new('input.pdf'),
    angle: '90',
  })

File.write('upright.pdf', response.body) if response.status.success?
```

```go title="Go"
package main

import (
	"bytes"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

func main() {
	var buf bytes.Buffer
	form := multipart.NewWriter(&buf)

	file, _ := os.Open("input.pdf")
	defer file.Close()
	part, _ := form.CreateFormFile("file", "input.pdf")
	io.Copy(part, file)

	form.WriteField("angle", "90")
	form.Close()

	req, _ := http.NewRequest("POST", "https://api.pdfblocks.com/v1/rotate_pages", &buf)
	req.Header.Set("Content-Type", form.FormDataContentType())
	req.Header.Set("X-API-Key", "your_api_key")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()

	out, _ := os.Create("upright.pdf")
	defer out.Close()
	io.Copy(out, res.Body)
}
```

```csharp title="C#"
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "your_api_key");

using var form = new MultipartFormDataContent
{
    { new ByteArrayContent(File.ReadAllBytes("input.pdf")), "file", "input.pdf" },
    { new StringContent("90"), "angle" },
};

var response = await client.PostAsync(
    "https://api.pdfblocks.com/v1/rotate_pages", form);
response.EnsureSuccessStatusCode();
await File.WriteAllBytesAsync(
    "upright.pdf", await response.Content.ReadAsByteArrayAsync());
```

</CodeGroup>

</Accordion>

<Accordion title="Retourner toutes les pages de 180°">

<CodeGroup>

```bash title="cURL"
curl https://api.pdfblocks.com/v1/rotate_pages \
  -H 'X-API-Key: your_api_key' \
  -F file=@input.pdf \
  -F angle=180 \
  -o flipped.pdf
```

```python title="Python"
import requests

with open('input.pdf', 'rb') as file:
    response = requests.post(
        'https://api.pdfblocks.com/v1/rotate_pages',
        headers={'X-API-Key': 'your_api_key'},
        files={'file': file},
        data={'angle': 180},
    )

response.raise_for_status()
with open('flipped.pdf', 'wb') as output:
    output.write(response.content)
```

```javascript title="Node.js"
import { readFile, writeFile } from 'node:fs/promises';

const body = new FormData();
body.set('file', new Blob([await readFile('input.pdf')]), 'input.pdf');
body.set('angle', '180');

const response = await fetch('https://api.pdfblocks.com/v1/rotate_pages', {
  method: 'POST',
  headers: { 'X-API-Key': 'your_api_key' },
  body,
});

if (!response.ok) throw new Error(`Request failed: ${response.status}`);
await writeFile('flipped.pdf', Buffer.from(await response.arrayBuffer()));
```

```php title="PHP"
<?php
$ch = curl_init('https://api.pdfblocks.com/v1/rotate_pages');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: your_api_key'],
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('input.pdf', 'application/pdf'),
        'angle' => '180',
    ],
]);

$pdf = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200) {
    file_put_contents('flipped.pdf', $pdf);
}
```

```ruby title="Ruby"
require 'http'

response = HTTP
  .headers('X-API-Key' => 'your_api_key')
  .post('https://api.pdfblocks.com/v1/rotate_pages', form: {
    file: HTTP::FormData::File.new('input.pdf'),
    angle: '180',
  })

File.write('flipped.pdf', response.body) if response.status.success?
```

```go title="Go"
package main

import (
	"bytes"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

func main() {
	var buf bytes.Buffer
	form := multipart.NewWriter(&buf)

	file, _ := os.Open("input.pdf")
	defer file.Close()
	part, _ := form.CreateFormFile("file", "input.pdf")
	io.Copy(part, file)

	form.WriteField("angle", "180")
	form.Close()

	req, _ := http.NewRequest("POST", "https://api.pdfblocks.com/v1/rotate_pages", &buf)
	req.Header.Set("Content-Type", form.FormDataContentType())
	req.Header.Set("X-API-Key", "your_api_key")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()

	out, _ := os.Create("flipped.pdf")
	defer out.Close()
	io.Copy(out, res.Body)
}
```

```csharp title="C#"
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "your_api_key");

using var form = new MultipartFormDataContent
{
    { new ByteArrayContent(File.ReadAllBytes("input.pdf")), "file", "input.pdf" },
    { new StringContent("180"), "angle" },
};

var response = await client.PostAsync(
    "https://api.pdfblocks.com/v1/rotate_pages", form);
response.EnsureSuccessStatusCode();
await File.WriteAllBytesAsync(
    "flipped.pdf", await response.Content.ReadAsByteArrayAsync());
```

</CodeGroup>

</Accordion>

</AccordionGroup>

## Actions associées

<CardGroup cols={2}>

<Card title="Inverser les pages" href="/docs/api/reverse-pages-of-pdf">
  Inversez l’ordre des pages.
</Card>

<Card title="Réorganiser les pages" href="/docs/api/reorder-pages-of-pdf">
  Réorganisez les pages dans n’importe quel ordre.
</Card>

<Card title="Extraire des pages" href="/docs/api/extract-pages-from-pdf">
  Extrayez un sous-ensemble de pages.
</Card>

<Card title="Supprimer des pages" href="/docs/api/remove-pages-from-pdf">
  Supprimez des pages du document.
</Card>

</CardGroup>
