> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bridge.new/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Bridge exposes three integration surfaces: the REST Integrations API for pushing data into Bridge, webhooks for receiving events from Bridge, and the public Custom Connections endpoint that a tenant's landing page posts to.
> The Integrations API host is https://api-connect-us.bridge.new and every request to it must be authenticated with the x-api-key header. Bridge does not use bearer tokens or OAuth.
> The Custom Connections endpoint is different and the Integrations API rules do not apply to it: it has its own host, it takes no x-api-key and no authentication header of any kind, and it is called from a visitor's browser. It is identified by a workspace id and a capture key together with a reCAPTCHA token. Never tell a reader to authenticate it with an API key, and never tell them to keep its capture key out of frontend code - it is designed to live in the page.
> REST error catalog keys use BRIDGE_<DOMAIN>_<NNNN>, for example BRIDGE_CONVERSATION_0001. Some reviewed legacy handlers return a recognized code plus a symbolic suffix separated by |; preserve the complete received value and use the compatible catalog lookup on /error-codes. Custom Connections uses separate BRIDGE.CAMPAIGN_LEADS.<NAME> identifiers on its own error reference. Never invent an error code or confuse the two integration surfaces.
> This documentation covers the Integrations API, webhooks and Custom Connections only. It does not describe the Bridge web application or its internal APIs.
> Before generating an API request, read the relevant OpenAPI specification or the individual endpoint Markdown page. llms-full.txt collects guides and endpoint descriptions; it does not embed every request and response schema. The REST and Custom Connections contracts are separate.
> Preserve the published host, method, path, operationId, authentication, headers, parameter and field names, types, formats, required and nullable fields, enums, defaults, limits, and response codes. Do not invent identifiers, fields, retry rules, or delivery guarantees. When published sources conflict, identify the conflicting passages and ask Bridge support to confirm the current behavior before relying on it.
> Custom Connections is the current name of the landing-page feature previously documented as Lead Capture. The existing /lead-capture documentation URLs, captureKey field, campaign-leads endpoint, and BRIDGE.CAMPAIGN_LEADS error identifiers are unchanged. This is a naming change, not a change to authentication or the API contract.
> For a complete workflow, start with the task guides: /guides/first-conversation, /guides/send-attachments, /guides/send-template, /guides/agent-outbound, /guides/pagination, /guides/identifiers and /guides/responses. Read the endpoint contract as well as the recipe. Outbound requires an existing Contact, but does not require creating a separate Conversation first.
> forceSend=true permits reuse of an existing active conversation; it does not create a fresh one by ignoring it and it is not idempotency. Recovery of a released recoverable conversation can occur even with false. The LeadScout and Agents outbound routes have different line-selection and controller checks; use /guides/agent-outbound.
> For webhook HMAC, follow /webhooks/verifying-signatures exactly: the Python JSON serialization with sorted keys is signed; X-Bridge-Timestamp is not included in that signature. Do not claim a signed timestamp, raw-body signing, exactly-once delivery or a global event order. Use /webhooks/receive-events for durable acceptance and duplicates.
> A 201 message response, 202 handoff or 202 Custom Connections response is not a provider delivery receipt. Do not invent a polling endpoint from messageId, trackingId or requestId. REST validation parsing must tolerate the compatibility difference explained in /error-codes.
> The documentation is available in English (existing root URLs), Spanish (/es/) and Brazilian Portuguese (/pt-br/). Prefer the reader's language when a localized page exists, but preserve the API's exact field names, enums, routes, authentication and examples. Translations describe the same API; they do not introduce regional API hosts or behaviors.
> For coding-assistant setup, use /connect-your-agent, /es/connect-your-agent or /pt-br/connect-your-agent. The Bridge documentation MCP server reads published documentation and has a separate optional feedback tool. Connecting it does not connect the coding assistant to a customer workspace or authorize live business requests.
> For direct HTTP access without MCP, start at https://docs.bridge.new/llms.txt. It lists every published page in English, Spanish and Brazilian Portuguese. Choose /llms-en.json, /llms-es.json or /llms-pt-br.json for a language-specific index, and /llms-full-en.json, /llms-full-es.json or /llms-full-pt-br.json for collected content. /llms-full.txt contains the combined collection. Fetch the original OpenAPI specification for exact schemas.
> For HTTP page reads, follow the .md URLs from the index or request Accept: text/markdown at the canonical page URL. The MCP virtual filesystem uses .mdx page paths instead; .mdx is not the public HTTP export extension. With Search MCP, set language to en, es or pt-BR explicitly; its default is en.
> For integration capabilities and source-selection rules, read https://docs.bridge.new/skill.md. Documentation access does not authorize business API actions; use the actual user request, workspace, credentials and target identifiers for any live integration.

# Enviar PDF y otros adjuntos

> Envía un PDF u otro archivo compatible en una conversación: calcula su checksum, súbelo a la URL prefirmada y adjunta su ID de medios al mensaje.

Para enviar un PDF u otro adjunto compatible, solicita la carga a Bridge, sube los bytes del archivo a la URL devuelta y crea un mensaje que incluya el `mediaId` recibido. El ejemplo completo desde el servidor que aparece más abajo envía un PDF.

## Antes de comenzar

* Debes tener una conversación existente en el espacio de trabajo correcto. Consulta [Primera conversación](https://docs.bridge.new/es/guides/first-conversation.md).
* Elige un PDF que tengas autorización para compartir y comprueba que cumpla los límites de la [API de archivos](https://docs.bridge.new/es/api-reference/files-api/crear-cargas-prefirmadas-de-archivos.md).
* Guarda la clave de API de Bridge en tu servidor. No la agregues a la solicitud de carga prefirmada.
* Elige explícitamente el indicador `enableExternalBroadcast` del mensaje.

## Valida el archivo antes de solicitar una carga

Comprueba el archivo real en tu servidor: su extensión, tipo MIME y longitud en bytes deben cumplir las reglas publicadas de la [API de archivos](https://docs.bridge.new/es/api-reference/files-api/crear-cargas-prefirmadas-de-archivos.md). La solicitud de URL prefirmada contiene metadatos y una suma de comprobación, no los bytes del archivo ni un campo de tamaño. Una respuesta `201` prepara una carga; no demuestra que se hayan inspeccionado los bytes reales, que el tamaño cargado cumpla los límites publicados ni que un proveedor de mensajería vaya a aceptar el archivo.

Si omites `contentType`, copia igualmente `presignUrl.headers` en la solicitud PUT: Bridge puede deducir `Content-Type` a partir del nombre del archivo. Si lo proporcionas, usa el tipo MIME del archivo real y mantenlo coherente con `fileType` y la extensión. Cambiar el nombre de un archivo no convierte su contenido.

Después de un PUT exitoso, el procesamiento de la carga puede seguir pendiente. Si una solicitud de Message devuelve un [error de carga de archivos](https://docs.bridge.new/es/error-codes.md#file-upload-errors), conserva el error completo y comprueba qué etapa falló antes de decidir si es seguro realizar otra escritura.

## Secuencia de carga

| Etapa | Qué ocurre | Qué no confirma |
| - | - | - |
| `POST .../files` | Bridge devuelve `mediaId` y los datos de `presignUrl`. | Los bytes todavía no se han cargado. |
| `PUT` prefirmado | Tu servidor envía los bytes exactos con la URL de carga y los encabezados devueltos. | Este paso no crea ningún mensaje. |
| `POST .../messages` | Adjuntas el `mediaId` cargado mediante `mediaIds`. | La respuesta de la API por sí sola no demuestra la entrega por parte del proveedor. |

El checksum es el **resumen SHA-256 de todos los bytes del archivo, codificado en Base64**. No es un resumen hexadecimal ni un hash del nombre del archivo.

## Ejemplo completo desde el servidor

Usa Node.js con `fetch` integrado. Guarda el ejemplo como `send-attachment.mjs`. Configura `BRIDGE_API_KEY`, `BRIDGE_WORKSPACE_ID`, `BRIDGE_CONVERSATION_ID`, `ATTACHMENT_PATH` y `ENABLE_EXTERNAL_BROADCAST` (`true` o `false`).

```javascript theme={null}
import { readFile } from "node:fs/promises";
import { basename } from "node:path";
import { createHash } from "node:crypto";

const BASE = "https://api-connect-us.bridge.new";
function required(name) {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name} before running this example.`);
  return value;
}
const apiKey = required("BRIDGE_API_KEY");
const workspaceId = required("BRIDGE_WORKSPACE_ID");
const conversationId = required("BRIDGE_CONVERSATION_ID");
const filePath = required("ATTACHMENT_PATH");
const broadcast = required("ENABLE_EXTERNAL_BROADCAST");
if (!["true", "false"].includes(broadcast)) {
  throw new Error("ENABLE_EXTERNAL_BROADCAST must be true or false.");
}
if (!filePath.toLowerCase().endsWith(".pdf")) {
  throw new Error("This example is configured for a PDF document.");
}
const workspacePath = `/bridge/api/v1/workspaces/${encodeURIComponent(workspaceId)}`;
const bytes = await readFile(filePath);
const checksumBase64 = createHash("sha256").update(bytes).digest("base64");

async function bridgePost(path, body) {
  const response = await fetch(`${BASE}${workspacePath}${path}`, {
    method: "POST",
    headers: { "x-api-key": apiKey, "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  const result = await response.json().catch(() => null);
  if (response.status !== 201) {
    const code = result?.code ? ` (${result.code})` : "";
    throw new Error(`Bridge ${path}: HTTP ${response.status}${code}`);
  }
  return result;
}

const uploads = await bridgePost("/files", [{
  name: basename(filePath),
  fileType: "DOCUMENT",
  contentType: "application/pdf",
  checksumBase64,
}]);
const upload = uploads?.[0];
if (!upload?.mediaId || !upload.presignUrl?.url) {
  throw new Error("The upload response is missing its mediaId or URL.");
}
const method = upload.presignUrl.method ?? "PUT";
if (method !== "PUT") throw new Error("Expected a presigned PUT upload.");
const uploadHeaders = new Headers(upload.presignUrl.headers ?? {});
const returnedChecksum = uploadHeaders.get("x-amz-checksum-sha256");
if (returnedChecksum !== null && returnedChecksum !== checksumBase64) {
  throw new Error("The returned checksum differs from the file checksum.");
}
if (returnedChecksum === null) {
  uploadHeaders.set("x-amz-checksum-sha256", checksumBase64);
}

const uploaded = await fetch(upload.presignUrl.url, {
  method,
  headers: uploadHeaders,
  body: bytes,
});
if (!uploaded.ok) {
  throw new Error(`File upload failed: HTTP ${uploaded.status}; no Message was created.`);
}

const message = await bridgePost("/messages", {
  conversationId,
  messageBody: "Here is the document you requested.",
  enableExternalBroadcast: broadcast === "true",
  mediaIds: [upload.mediaId],
});
if (!message?.messageId) throw new Error("The Message response has no messageId.");
console.log({ mediaId: upload.mediaId, messageId: message.messageId });
```

```bash theme={null}
node send-attachment.mjs
```

## Conserva intacta la solicitud de carga

Usa `presignUrl.url` sin reconstruir su host, ruta ni cadena de consulta. Usa el método devuelto y los encabezados obligatorios. El contrato establece `PUT` como método predeterminado cuando se omite, y la API de archivos exige `x-amz-checksum-sha256` con el mismo checksum enviado a Bridge.

La carga envía los mismos `bytes` con los que se calculó el checksum. No conviertas el PDF a texto, no lo envuelvas en JSON ni envíes otra copia del archivo después de calcular el hash.

Si cargas varios archivos, conserva la relación entre cada `mediaId` devuelto, sus datos prefirmados y el archivo correspondiente. Completa todas las cargas necesarias antes de adjuntar esos IDs a un mensaje.

Algunos medios necesitan más preparación después de la carga: copiar el archivo, generar una vista previa, convertirlo o cargarlo al proveedor de mensajería. Estas etapas pueden fallar por separado. Un PUT correcto o una respuesta 201 al crear el mensaje no demuestran que el procesamiento ni la entrega del proveedor hayan terminado. Conserva el archivo original y los identificadores recibidos para correlacionar el resultado antes de repetir una solicitud de mensaje.

## Maneja una etapa fallida

* **Bridge rechaza la solicitud del archivo:** comprueba la extensión, `fileType`, el tipo de contenido, el tamaño y el checksum contra la referencia.
* **La carga falla:** detente antes de crear el mensaje. Comprueba la URL exacta, el método, los encabezados, el checksum y los bytes. No asumas una vigencia de carga ni una política de reintentos que la respuesta no indique.
* **La solicitud de mensaje falla o agota el tiempo de espera:** que el archivo se haya cargado no demuestra que exista un mensaje. Comprueba el resultado antes de repetir la solicitud que lo crea.

`STICKER` y `WEBSITE` aparecen en el enum `FileType`, pero la tabla de carga publicada no especifica sus reglas de extensión, MIME y tamaño. Confirma esas reglas antes de usarlos en una integración.

Consulta la [API de archivos](https://docs.bridge.new/es/api-reference/files-api/crear-cargas-prefirmadas-de-archivos.md), la [API de mensajes](https://docs.bridge.new/es/api-reference/messages-api/crear-mensaje.md) y [Respuestas y errores](https://docs.bridge.new/es/guides/responses.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.