# Dividir un PDF en grupos de páginas

Divida un PDF en los grupos de páginas que usted defina, donde cada grupo se convierte en un documento de salida.

Divida un documento PDF en los grupos de páginas que usted defina: cada grupo
se convierte en un PDF de salida, en el orden escrito. Dentro de un grupo,
las páginas y los rangos siguen [la sintaxis de páginas
ordenada](/docs/api/selecting-pages), así que salen exactamente como se
listan. Esta acción devuelve varios documentos, empaquetados en una sola
respuesta según la cabecera `Accept`. La API es *stateless*: su documento se
procesa en la región y nunca se almacena.

## Endpoint

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

Disponible en todas las regiones. Consulte [Regiones y residencia de
datos](/docs/api/regions-and-data-residency) para el enrutamiento y la
residencia de datos.

| Región           | URL                                                  |
| ---------------- | ---------------------------------------------------- |
| Global           | `https://api.pdfblocks.com/v1/split_by_groups`       |
| Estados Unidos   | `https://us.api.pdfblocks.com/v1/split_by_groups`    |
| HIPAA de EE. UU. | `https://hipaa.api.pdfblocks.com/v1/split_by_groups` |
| Unión Europea    | `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`    |
| Australia        | `https://au.api.pdfblocks.com/v1/split_by_groups`    |
| Japón            | `https://jp.api.pdfblocks.com/v1/split_by_groups`    |
| India            | `https://in.api.pdfblocks.com/v1/split_by_groups`    |
| Brasil           | `https://br.api.pdfblocks.com/v1/split_by_groups`    |

## Autenticación

Autentique cada solicitud con su clave de API secreta en la cabecera
`X-API-Key`, por HTTPS. Cree y administre sus claves desde el
[dashboard](https://dashboard.pdfblocks.com). Consulte
[Autenticación](/docs/api/authentication) para más detalles.

## Solicitud

El endpoint acepta un cuerpo de solicitud `multipart/form-data`.

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

<ParamField name="groups" type="string" required>
  Los grupos de páginas que se producirán, siguiendo [la sintaxis de grupos
  de páginas](#grupos-de-páginas). Los grupos se separan con `;`; dentro de un
  grupo, las páginas y los rangos se separan con `,` y siguen las reglas de
  orden. Cada grupo se convierte en un PDF de salida, en el orden escrito.
  Por ejemplo, `2..8,29;1` produce dos PDF: las páginas 2 a 8 y luego la 29,
  y la página 1.
</ParamField>

### Grupos de páginas

Los grupos se separan con `;`. Dentro de cada grupo, las páginas y los rangos
siguen la sintaxis ordenada: el orden y las repeticiones importan, una página
nombrada dos veces se emite dos veces y un rango puede ir hacia atrás. Cada
grupo se convierte en un PDF de salida, emitido en el orden en que están
escritos los grupos.

Por ejemplo, `2..8,29;1` produce dos documentos:

| Grupo      | PDF de salida | Páginas                                       |
| ---------- | ------------- | --------------------------------------------- |
| `2..8,29`  | `00001.pdf`   | Las páginas 2, 3, 4, 5, 6, 7, 8 y luego la 29 |
| `1`        | `00002.pdf`   | La página 1                                   |

Dentro de un grupo, `groups` comparte la semántica ordenada de `page_order`.
Consulte [Seleccionar páginas](/docs/api/selecting-pages) para ver la
referencia completa.

## Ejemplos

Divida un documento en dos PDF: las páginas 2 a 8 y luego la 29, y la 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>

## Respuesta

Esta acción devuelve varios documentos, empaquetados en una sola respuesta
según la cabecera de solicitud `Accept`: consulte [Formatos de respuesta y
negociación de contenido](/docs/api/response-formats) para ver la referencia
completa de la negociación. Sin cabecera `Accept`, la opción predeterminada
es un archivo ZIP:

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

Seleccione el empaquetado con la cabecera `Accept`:

| Cabecera `Accept`    | Respuesta                                                      |
| -------------------- | -------------------------------------------------------------- |
| *(no se envía)*      | `application/zip`: la opción predeterminada                    |
| `application/zip`    | Un archivo ZIP con los PDF de salida                           |
| `application/json`   | Un sobre JSON con los documentos codificados en base64         |
| `multipart/mixed`    | Un PDF por parte                                               |
| cualquier otra cosa  | `406 Not Acceptable`                                           |

La API produce un documento de salida por grupo, en el orden en que están
escritos los grupos, con los nombres `00001.pdf`, `00002.pdf` y así
sucesivamente.

<Tip>
  Para ver código de principio a fin que llama a una acción de división y
  desempaqueta cada formato, ya sea extrayendo el ZIP, decodificando el sobre
  JSON o leyendo las partes multipart, consulte la guía [Dividir un
  PDF](/docs/api/splitting-a-pdf).
</Tip>

## Errores

Las solicitudes fallidas devuelven un cuerpo `application/problem+json`. El
error más habitual en este endpoint es un `400`, que se devuelve cuando falta
`groups`, está mal formado o hace referencia a una página que no existe en el
documento: el objeto `errors` nombra 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."]
  }
}
```

Si la cabecera `Accept` no coincide con `application/zip`, `application/json`
ni `multipart/mixed`, por ejemplo `Accept: application/pdf`, la API responde
con `406 Not Acceptable`. Omita `Accept` para tomar el ZIP predeterminado, o
solicite uno de los tipos de medio admitidos. Una `X-API-Key` ausente o no
válida devuelve un `401`. Consulte [Errores](/docs/api/errors) para ver todos
los códigos de estado y la forma completa de la respuesta.

## Recetas

Una variante habitual. Despliéguela para ver el código en todos los
lenguajes.

<AccordionGroup>

<Accordion title="Recibir las partes como un sobre JSON">

Envíe `Accept: application/json` para recibir todas las partes en línea en
una sola respuesta y después decodifique de base64 el `content` de cada
entrada en un archivo con el nombre de su `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>

## Acciones relacionadas

<CardGroup cols={2}>

<Card title="Dividir por número de páginas" href="/docs/api/split-pdf-by-page-count">
  Divida en partes de tamaño fijo.
</Card>

<Card title="Dividir en una página" href="/docs/api/split-pdf-at-page">
  Divida en dos documentos en un límite.
</Card>

<Card title="Reordenar páginas" href="/docs/api/reorder-pages-of-pdf">
  Reordene las páginas dentro de una sola salida.
</Card>

<Card title="Extraer páginas" href="/docs/api/extract-pages-from-pdf">
  Conserve un rango de páginas.
</Card>

</CardGroup>
