# Dividir um PDF em grupos de páginas

Divida um PDF em grupos de páginas que você define, em que cada grupo se torna um documento de saída.

Divida um documento PDF em grupos de páginas que você define: cada grupo se
torna um PDF de saída, na ordem em que foram escritos. Dentro de um grupo, as
páginas e os intervalos seguem a [sintaxe de páginas
ordenada](/docs/api/selecting-pages), portanto saem exatamente como foram
listados. Esta ação retorna vários documentos, empacotados em uma única resposta
de acordo com o cabeçalho `Accept`. A API é *stateless*: seu documento é processado
na própria região e nunca é armazenado.

## Endpoint

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

Disponível em todas as regiões. Consulte [Regiões e residência de
dados](/docs/api/regions-and-data-residency) para o roteamento e a residência
de dados.

| Região               | URL                                                  |
| -------------------- | ---------------------------------------------------- |
| Global               | `https://api.pdfblocks.com/v1/split_by_groups`       |
| Estados Unidos       | `https://us.api.pdfblocks.com/v1/split_by_groups`    |
| HIPAA Estados Unidos | `https://hipaa.api.pdfblocks.com/v1/split_by_groups` |
| União Europeia       | `https://eu.api.pdfblocks.com/v1/split_by_groups`    |
| Reino Unido          | `https://uk.api.pdfblocks.com/v1/split_by_groups`    |
| Canadá               | `https://ca.api.pdfblocks.com/v1/split_by_groups`    |
| Austrália            | `https://au.api.pdfblocks.com/v1/split_by_groups`    |
| Japão                | `https://jp.api.pdfblocks.com/v1/split_by_groups`    |
| Índia                | `https://in.api.pdfblocks.com/v1/split_by_groups`    |
| Brasil               | `https://br.api.pdfblocks.com/v1/split_by_groups`    |

## Autenticação

Autentique cada requisição com sua chave de API secreta no cabeçalho
`X-API-Key`, por HTTPS. Crie e gerencie suas chaves no
[dashboard](https://dashboard.pdfblocks.com). Consulte
[Autenticação](/docs/api/authentication) para mais detalhes.

## Requisição

O endpoint aceita um corpo de requisição `multipart/form-data`.

<ParamField name="file" type="file" required>
  O documento PDF de entrada.
</ParamField>

<ParamField name="groups" type="string" required>
  Os grupos de páginas a produzir, seguindo [a sintaxe de grupos de
  páginas](#grupos-de-páginas). Os grupos são separados por `;`; dentro de um
  grupo, as páginas e os intervalos são separados por `,` e seguem as regras
  ordenadas. Cada grupo se torna um PDF de saída, na ordem em que foram
  escritos. Por exemplo, `2..8,29;1` produz dois PDFs: as páginas 2 a 8 e depois
  a 29, e a página 1.
</ParamField>

### Grupos de páginas

Os grupos são separados por `;`. Dentro de cada grupo, as páginas e os
intervalos seguem a sintaxe ordenada: a ordem e as repetições importam, uma
página citada duas vezes é emitida duas vezes e um intervalo pode ir de trás
para frente. Cada grupo se torna um PDF de saída, emitido na ordem em que os
grupos foram escritos.

Por exemplo, `2..8,29;1` produz dois documentos:

| Grupo      | PDF de saída | Páginas                                        |
| ---------- | ------------ | ---------------------------------------------- |
| `2..8,29`  | `00001.pdf`  | As páginas 2, 3, 4, 5, 6, 7, 8 e, em seguida, a 29 |
| `1`        | `00002.pdf`  | A página 1                                     |

Dentro de um grupo, `groups` compartilha a semântica ordenada de `page_order`.
Consulte [Selecionar páginas](/docs/api/selecting-pages) para a referência
completa.

## Exemplos

Divida um documento em dois PDFs: as páginas 2 a 8 e depois a 29, e a página 1:

<CodeGroup>

```bash title="cURL"
curl https://api.pdfblocks.com/v1/split_by_groups \
  -H 'X-API-Key: your_api_key' \
  -F file=@input.pdf \
  -F groups='2..8,29;1' \
  -o parts.zip
```

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

with open('input.pdf', 'rb') as file:
    response = requests.post(
        'https://api.pdfblocks.com/v1/split_by_groups',
        headers={'X-API-Key': 'your_api_key'},
        files={'file': file},
        data={'groups': '2..8,29;1'},
    )

response.raise_for_status()
with open('parts.zip', '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('groups', '2..8,29;1');

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

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

```php title="PHP"
<?php
$ch = curl_init('https://api.pdfblocks.com/v1/split_by_groups');
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'),
        'groups' => '2..8,29;1',
    ],
]);

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

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

response = HTTP
  .headers('X-API-Key' => 'your_api_key')
  .post('https://api.pdfblocks.com/v1/split_by_groups', form: {
    file: HTTP::FormData::File.new('input.pdf'),
    groups: '2..8,29;1',
  })

File.write('parts.zip', 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("groups", "2..8,29;1")
	form.Close()

	req, _ := http.NewRequest("POST", "https://api.pdfblocks.com/v1/split_by_groups", &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("parts.zip")
	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("2..8,29;1"), "groups" },
};

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

</CodeGroup>

## Resposta

Esta ação retorna vários documentos, empacotados em uma única resposta de
acordo com o cabeçalho de requisição `Accept`. Consulte [Formatos de resposta e negociação
de conteúdo](/docs/api/response-formats) para a referência completa da
negociação. Sem o cabeçalho `Accept`, o padrão é um arquivo ZIP:

```http
HTTP/1.1 200 OK
Content-Type: application/zip
```

Selecione o empacotamento com o cabeçalho `Accept`:

| Cabeçalho `Accept`   | Resposta                                                        |
| -------------------- | --------------------------------------------------------------- |
| *(nenhum enviado)*   | `application/zip`: o padrão                                     |
| `application/zip`    | Um arquivo ZIP com os PDFs de saída                             |
| `application/json`   | Um envelope JSON com os documentos codificados em base64        |
| `multipart/mixed`    | Um PDF por parte                                                |
| qualquer outra coisa | `406 Not Acceptable`                                            |

A API produz um documento de saída por grupo, na ordem em que os grupos foram
escritos, com os nomes `00001.pdf`, `00002.pdf` e assim por diante.

<Tip>
  Para ver código de ponta a ponta que chama uma ação de divisão e desempacota
  cada formato (extrair o ZIP, decodificar o envelope JSON ou ler as partes
  multipart), consulte o guia [Dividir um PDF](/docs/api/splitting-a-pdf).
</Tip>

## Erros

Requisições com falha retornam um corpo `application/problem+json`. O erro mais
comum neste endpoint é um `400`, retornado quando `groups` está ausente ou malformado,
ou quando referencia uma página que não existe no documento. O objeto `errors`
nomeia cada campo:

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/400",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "groups": ["The groups field references a page that does not exist in the document."]
  }
}
```

Se o cabeçalho `Accept` não corresponder a nenhum dos tipos `application/zip`,
`application/json` ou `multipart/mixed`, por exemplo `Accept: application/pdf`,
a API responde com `406 Not Acceptable`. Omita `Accept` para ficar com o ZIP
padrão ou peça um dos tipos de mídia compatíveis. Uma `X-API-Key` ausente ou
inválida retorna um `401`. Consulte [Erros](/docs/api/errors) para todos os
códigos de status e o formato completo da resposta.

## Receitas

Uma variação comum. Expanda-a para ver o código em todas as linguagens.

<AccordionGroup>

<Accordion title="Receber as partes como um envelope JSON">

Envie `Accept: application/json` para receber todas as partes em linha em uma
única resposta e depois decodifique de base64 o `content` de cada entrada em um
arquivo nomeado a partir do seu `name`:

<CodeGroup>

```bash title="cURL"
curl https://api.pdfblocks.com/v1/split_by_groups \
  -H 'X-API-Key: your_api_key' \
  -H 'Accept: application/json' \
  -F file=@input.pdf \
  -F groups='2..8,29;1' \
  | jq -r '.documents[] | .name + " " + .content' \
  | while read -r name content; do
      echo "$content" | base64 --decode > "$name"
    done
```

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

with open('input.pdf', 'rb') as file:
    response = requests.post(
        'https://api.pdfblocks.com/v1/split_by_groups',
        headers={
            'X-API-Key': 'your_api_key',
            'Accept': 'application/json',
        },
        files={'file': file},
        data={'groups': '2..8,29;1'},
    )

response.raise_for_status()
for document in response.json()['documents']:
    with open(document['name'], 'wb') as output:
        output.write(base64.b64decode(document['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('groups', '2..8,29;1');

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

if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const { documents } = await response.json();
for (const doc of documents) {
  await writeFile(doc.name, Buffer.from(doc.content, 'base64'));
}
```

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

$body = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200) {
    foreach (json_decode($body, true)['documents'] as $document) {
        file_put_contents($document['name'], base64_decode($document['content']));
    }
}
```

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

response = HTTP
  .headers('X-API-Key' => 'your_api_key', 'Accept' => 'application/json')
  .post('https://api.pdfblocks.com/v1/split_by_groups', form: {
    file: HTTP::FormData::File.new('input.pdf'),
    groups: '2..8,29;1',
  })

if response.status.success?
  JSON.parse(response.body)['documents'].each do |document|
    File.write(document['name'], Base64.decode64(document['content']))
  end
end
```

```go title="Go"
package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"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("groups", "2..8,29;1")
	form.Close()

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

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

	var result struct {
		Documents []struct {
			Name    string `json:"name"`
			Content string `json:"content"`
		} `json:"documents"`
	}
	json.NewDecoder(res.Body).Decode(&result)

	for _, doc := range result.Documents {
		data, _ := base64.StdEncoding.DecodeString(doc.Content)
		os.WriteFile(doc.Name, data, 0644)
	}
}
```

```csharp title="C#"
using System.Text.Json;

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "your_api_key");
client.DefaultRequestHeaders.Add("Accept", "application/json");

using var form = new MultipartFormDataContent
{
    { new ByteArrayContent(File.ReadAllBytes("input.pdf")), "file", "input.pdf" },
    { new StringContent("2..8,29;1"), "groups" },
};

var response = await client.PostAsync(
    "https://api.pdfblocks.com/v1/split_by_groups", form);
response.EnsureSuccessStatusCode();

using var json = JsonDocument.Parse(
    await response.Content.ReadAsStringAsync());
foreach (var document in json.RootElement.GetProperty("documents").EnumerateArray())
{
    var name = document.GetProperty("name").GetString()!;
    var content = document.GetProperty("content").GetString()!;
    await File.WriteAllBytesAsync(name, Convert.FromBase64String(content));
}
```

</CodeGroup>

</Accordion>

</AccordionGroup>

## Ações relacionadas

<CardGroup cols={2}>

<Card title="Dividir por número de páginas" href="/docs/api/split-pdf-by-page-count">
  Divida em blocos de tamanho fixo.
</Card>

<Card title="Dividir em uma página" href="/docs/api/split-pdf-at-page">
  Divida em dois documentos em um ponto de corte.
</Card>

<Card title="Reordenar páginas" href="/docs/api/reorder-pages-of-pdf">
  Reordene as páginas dentro de uma única saída.
</Card>

<Card title="Extrair páginas" href="/docs/api/extract-pages-from-pdf">
  Mantenha um intervalo de páginas.
</Card>

</CardGroup>
