# Get an invoice reply API Reference

Returns a reply with its full `text`, without masking and without the quoted original
message.


## GET /v1/companies/{company_id}/invoice-replies/{reply_id}

**Get an invoice reply**

Returns a reply with its full `text`, without masking and without the quoted original
message.

### Authentication

Accepts any of:

- `ApiKeyAuth` (HTTP bearer, token format `beel_sk_*`)

### Parameters

- **company_id** (required) in path `string`: Unique identifier (UUID) of the company the operation acts on: its identifier, not its NIF. It is the only source of context: the account that owns it is derived from it, and the `BeeL-Active-Company` header plays no part. A company you do not reach answers `403`, and so does a company that does not exist, so the existence of a company in another account is never disclosed.
- **reply_id** (required) in path `string`: Unique identifier (UUID) of the reply, as returned by the list or by `POST .../invoice-replies`.

### Responses

#### 200: The reply

**Content `application/json`:**

- **success** (required) `boolean`: No description (example: true)
- **data** (required): The payload. An object for a single resource; an object holding the named collection (and its `pagination`) for a listing. Never a bare array at this level in v1.
- **meta** `ResponseMeta`
- **data** (required) `InvoiceReply`: A reply about an invoice, with its full text, `external_id` and file names.

#### 401: Missing or invalid authentication. Like every other error, `message`/`detail` is
localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English when the
header is missing or asks for none of those.


**Content `application/json`:**

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

**Example:**

```json
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Authentication is required to access this resource"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
```

#### 403: One of:
- `ACTIVE_COMPANY_NOT_ACCESSIBLE`: your account does not own or manage this company.
- `INSUFFICIENT_SCOPE`: the credential lacks `invoice-replies:read`, a privileged scope
  that a key created without selecting scopes does not hold.


**Content `application/json`:**

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

#### 404: The reply does not exist or belongs to another company or environment
(`INVOICE_REPLY_NOT_FOUND`).


**Content `application/json`:**

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

#### 429: Rate limit exceeded. `RATE_LIMIT_EXCEEDED` when the request rate of your credential is
over its limit; `TOO_MANY_REQUESTS` when an email the operation sends is held back because
too many went out to that recipient in a short time. Either way, retry after the
`Retry-After` seconds.

`QUOTA_EXCEEDED` is the other `429`: the operation would go over a quota of your plan
for the current period (issued invoices, for instance). Retrying does not help until the
quota resets or the plan changes. `error.details` carries `feature_code`,
`current_usage`, `quota_limit` and `reset_date`, and `RateLimit-Reset` the seconds until
the reset when it is known.


**Headers:**

- `Retry-After` `integer`: Seconds until the rate limit resets
- `RateLimit-Limit` `integer`: Maximum requests allowed in the window
- `RateLimit-Remaining` `integer`: Remaining requests in the current window
- `RateLimit-Reset` `integer`: Seconds until the current window resets

**Content `application/json`:**

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

**Example:**

```json
{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Please try again in 60 seconds."
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
```

#### 500: Internal server error

**Content `application/json`:**

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

**Example:**

```json
{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Internal server error"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
```

#### default: Any status code the operation does not list above. Every operation declares it, so a
generated client always has a branch to fall into and never loses the cause of a failure
it did not anticipate.

This is where the transport-level answers land — `405`, `406`, `415` and `429` — together
with any status a future version of the API starts returning. All of them carry the same
error envelope as the codes listed explicitly, so `error.code` is what tells them apart:
switching on the status code alone is not enough. See «Transport-level errors» in the
API description for when each one is produced.

A `402` carrying `SUBSCRIPTION_REQUIRED` lands here when the account has no active
subscription. `error.details` says why and what to do: `current_status` (absent if it
never had one), `required_permission` and `action`.

A `503` carrying `SERVICE_UNAVAILABLE` lands here too, with a `Retry-After` header: a
dependency of BeeL itself (the database, the email provider) was momentarily
unavailable and nothing was done. Retry after those seconds.

A `502` carrying `EXTERNAL_SERVICE_ERROR` also lands here: an outbound integration the
operation depends on failed or did not answer in time. It is a transient condition — retry
with the same `Idempotency-Key` where the operation accepts one.

One exception to the envelope: a failure of the network edge that never reaches the
application (`502`, `503`, `504`, `524`) is generated by Cloudflare and its body is not
BeeL's — it may not even be JSON. Treat those as "no answer", and retry.


**Content `application/json`:**

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

**Example:**

```json
{
  "success": false,
  "error": {
    "code": "UNSUPPORTED_MEDIA_TYPE",
    "message": "Unsupported media type: text/plain. Supported: application/json"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
```

---

# Related Schema Definitions

## InvoiceReplyResponse

- **success** (required) `boolean`: No description (example: true)
- **data** (required): The payload. An object for a single resource; an object holding the named collection (and its `pagination`) for a listing. Never a bare array at this level in v1.
- **meta** `ResponseMeta`
- **data** (required) `InvoiceReply`: A reply about an invoice, with its full text, `external_id` and file names.

## SuccessResponse

The envelope every successful JSON response of the BeeL. API is wrapped in. There are no
bare resources in v1 and none are planned: the payload always hangs off `data`.

- A **single resource** is an object in `data`.
- A **collection** hangs off a named key inside `data`, together with its `pagination`,
  also inside `data` — `data: {invoices: [...], pagination: {...}}`.
- A collection carries `pagination` unless its operation declares itself a **closed
  catalogue**: a fixed, bounded list with nothing to page through. The declaration is
  explicit in the operation; a missing `pagination` is never something to infer.
- `GET /v1/accounts` pages by cursor (`data: {accounts: [...], next_cursor}`). It is a
  documented variant of pagination, not another envelope.

Putting the array straight into `data` with `pagination` as its sibling is the shape a v2
would adopt; v1 is not being flipped to it.

- **success** (required) `boolean`: No description (example: true)
- **data** (required): The payload. An object for a single resource; an object holding the named collection (and its `pagination`) for a listing. Never a bare array at this level in v1.
- **meta** `ResponseMeta`

## ResponseMeta

- **timestamp** `string` (date-time): No description (example: "2025-01-15T10:30:00Z")
- **request_id** `string`: No description (example: "4bf92f3577b34da6a3ce929d0e0e4736")

## InvoiceReply

A reply about an invoice, with its full text, `external_id` and file names.

- **id** (required) `string` (uuid): No description (example: "3f0c9a1e-6b2d-4c8f-a1e5-7d9b0c2e4f61")
- **channel** (required) `InvoiceReplyChannel`: Where the customer wrote: the medium, not the `provider` of the connection that brought it (an email is `EMAIL` whatever received it). More values may be added: treat an unknown one like `OTHER`. - `EMAIL`: an email; `sender.address` is an email address. - `WHATSAPP`: `sender.address` is a phone number in E.164 format. - `TELEGRAM`: `sender.address` is the user identifier on Telegram. - `SLACK`: `sender.address` is the user identifier on Slack. - `SMS`: `sender.address` is a phone number in E.164 format. - `OTHER`: any other channel, such as the chat of your product.
- **authenticated_by** (required) `InvoiceReplyAuthentication`: What links the message to its invoice, never who wrote it (`sender` is not verified). More values may be added: treat an unknown one like `API_KEY`. - `REPLY_TOKEN`: an answer to the email of one invoice, sent to the address unique to that email. - `API_KEY`: registered by an integrator with `POST .../invoice-replies`, who chose the invoice.
- **connection_id** (required) `string` (uuid): The connection of the company the message arrived through (`.../connections/{connection_id}`). `null` when it was registered with `POST .../invoice-replies`: you received it, not BeeL. (example: "8c3e1f7a-2b4d-4e6f-9a1c-5d7b3e9f2a41")
- **invoice_id** (required) `string` (uuid): The invoice the message is about. Every reply has one today; channels added in the future may store a reply without it, so handle `null`. (example: "b71d5e2a-9c3f-4a7b-8e10-2f6d4c8a9b13")
- **invoice_number** (required) `string`: Number of that invoice; `null` when `invoice_id` is `null`. (example: "F2026-0142")
- **customer_id** (required) `string` (uuid): The customer of the invoice; `null` when the invoice has a one-off recipient or `invoice_id` is `null`. (example: "7a2c9e14-3b5d-4f6a-8c0e-1d2b3a4c5e6f")
- **status** (required) `InvoiceReplyStatus`: Where the reply is in its lifecycle. More values will be added: treat an unknown value as an open reply. - `RECEIVED`: the reply is stored.
- **received_at** (required) `string` (date-time): When the message was received, in UTC: when BeeL. received it, or the moment given when it was registered. (example: "2026-11-03T09:12:44Z")
- **subject** (required) `string`: Subject of the message, with tax IDs, IBANs, email addresses and phone numbers masked. `null` when the message has none, as on every channel but `EMAIL`, and once the reply is past its retention of 12 months after `received_at`. (example: "RE: Factura F2026-0142")
- **excerpt** (required) `string`: First paragraph of the text of the message, without the quoted original email, with tax IDs, IBANs, email addresses and phone numbers replaced by `[NIF]`, `[IBAN]`, `[EMAIL]` and `[PHONE]`. `null` when the message has no text, and once the reply is past its retention of 12 months after `received_at`. (example: "Hola, el CIF que aparece no es el nuestro, es [NIF]. ¿Podéis corregirla?")
- **sender** (required) `InvoiceReplySender`: Who the message says it comes from, as the channel reported it or as the integrator sent it. It is not verified: never use it alone to authorize a change.
- **external_id** (required) `string`: Identifier of the message on its channel: the `Message-ID` of the email, without angle brackets, or the identifier sent when it was registered. A message is stored once per `channel` and `external_id` in each company and environment. `null` once the reply is past its retention of 12 months after `received_at`; the message still cannot be registered again. (example: "CAH7xQ2b9pLk3mZ0@mail.distribuciones-ejemplo.es")
- **attachments** (required) `array[InvoiceReplyAttachment]`: Attachments of the message. Empty when it has none; `null` once the reply is past its retention of 12 months after `received_at`.
- **text** (required) `string`: Text of the message without the quoted original email and without masking. HTML is converted to plain text. On the `EMAIL` channel, link annotations such as `<mailto:...>` that only repeat the text before them are removed. `null` when the message has no text, as a photo without a caption, and once the reply is past its retention of 12 months after `received_at`. (example: "Hola, el CIF que aparece no es el nuestro, es B87654315. ¿Podéis corregirla?\nGracias,\nLaura")
- **is_text_truncated** (required) `boolean`: `true` when the text was longer than 20,000 characters and was cut. (example: false)

## ErrorResponse

Error response shared by all BeeL. APIs.

The payload carries **two contracts at once** (additive, non-breaking):

- **Legacy** (`success`, `error.{code,message,details}`, `meta`) — kept
  intact for existing consumers.
- **RFC 9457** (`type`, `title`, `detail`, `instance`) — new fields
  for integrators following Problem Details for HTTP APIs. The
  `type` URI is the stable, shareable link to the error's
  documentation page (e.g. `https://docs.beel.es/errors/{code}`).

Future migration: the legacy fields will be deprecated via
`Deprecation`/`Sunset` headers after a sufficient adoption window,
and the response Content-Type will move to
`application/problem+json`.

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

## ErrorDetail

- **code** (required) `string`: No description (example: "VALIDATION_ERROR")
- **message** (required) `string`: No description (example: "The provided data is not valid")
- **details** `object`: No description (example: {"field":"specific error message"})

## InvoiceReplyBase

What every view of a reply carries. 12 months after `received_at`, its content, subject,
sender, attachments and `external_id` become `null`; the rest stays.

- **id** (required) `string` (uuid): No description (example: "3f0c9a1e-6b2d-4c8f-a1e5-7d9b0c2e4f61")
- **channel** (required) `InvoiceReplyChannel`: Where the customer wrote: the medium, not the `provider` of the connection that brought it (an email is `EMAIL` whatever received it). More values may be added: treat an unknown one like `OTHER`. - `EMAIL`: an email; `sender.address` is an email address. - `WHATSAPP`: `sender.address` is a phone number in E.164 format. - `TELEGRAM`: `sender.address` is the user identifier on Telegram. - `SLACK`: `sender.address` is the user identifier on Slack. - `SMS`: `sender.address` is a phone number in E.164 format. - `OTHER`: any other channel, such as the chat of your product.
- **authenticated_by** (required) `InvoiceReplyAuthentication`: What links the message to its invoice, never who wrote it (`sender` is not verified). More values may be added: treat an unknown one like `API_KEY`. - `REPLY_TOKEN`: an answer to the email of one invoice, sent to the address unique to that email. - `API_KEY`: registered by an integrator with `POST .../invoice-replies`, who chose the invoice.
- **connection_id** (required) `string` (uuid): The connection of the company the message arrived through (`.../connections/{connection_id}`). `null` when it was registered with `POST .../invoice-replies`: you received it, not BeeL. (example: "8c3e1f7a-2b4d-4e6f-9a1c-5d7b3e9f2a41")
- **invoice_id** (required) `string` (uuid): The invoice the message is about. Every reply has one today; channels added in the future may store a reply without it, so handle `null`. (example: "b71d5e2a-9c3f-4a7b-8e10-2f6d4c8a9b13")
- **invoice_number** (required) `string`: Number of that invoice; `null` when `invoice_id` is `null`. (example: "F2026-0142")
- **customer_id** (required) `string` (uuid): The customer of the invoice; `null` when the invoice has a one-off recipient or `invoice_id` is `null`. (example: "7a2c9e14-3b5d-4f6a-8c0e-1d2b3a4c5e6f")
- **status** (required) `InvoiceReplyStatus`: Where the reply is in its lifecycle. More values will be added: treat an unknown value as an open reply. - `RECEIVED`: the reply is stored.
- **received_at** (required) `string` (date-time): When the message was received, in UTC: when BeeL. received it, or the moment given when it was registered. (example: "2026-11-03T09:12:44Z")
- **subject** (required) `string`: Subject of the message, with tax IDs, IBANs, email addresses and phone numbers masked. `null` when the message has none, as on every channel but `EMAIL`, and once the reply is past its retention of 12 months after `received_at`. (example: "RE: Factura F2026-0142")
- **excerpt** (required) `string`: First paragraph of the text of the message, without the quoted original email, with tax IDs, IBANs, email addresses and phone numbers replaced by `[NIF]`, `[IBAN]`, `[EMAIL]` and `[PHONE]`. `null` when the message has no text, and once the reply is past its retention of 12 months after `received_at`. (example: "Hola, el CIF que aparece no es el nuestro, es [NIF]. ¿Podéis corregirla?")

## InvoiceReplyChannel

Where the customer wrote: the medium, not the `provider` of the connection that brought
it (an email is `EMAIL` whatever received it). More values may be added: treat an
unknown one like `OTHER`.

- `EMAIL`: an email; `sender.address` is an email address.
- `WHATSAPP`: `sender.address` is a phone number in E.164 format.
- `TELEGRAM`: `sender.address` is the user identifier on Telegram.
- `SLACK`: `sender.address` is the user identifier on Slack.
- `SMS`: `sender.address` is a phone number in E.164 format.
- `OTHER`: any other channel, such as the chat of your product.

Type: `string`

## InvoiceReplyAuthentication

What links the message to its invoice, never who wrote it (`sender` is not verified).
More values may be added: treat an unknown one like `API_KEY`.

- `REPLY_TOKEN`: an answer to the email of one invoice, sent to the address unique to
  that email.
- `API_KEY`: registered by an integrator with `POST .../invoice-replies`, who chose the
  invoice.

Type: `string`

## InvoiceReplyStatus

Where the reply is in its lifecycle. More values will be added: treat an unknown value as
an open reply.

- `RECEIVED`: the reply is stored.

Type: `string`

## InvoiceReplySender

Who the message says it comes from, as the channel reported it or as the integrator sent it. It is not verified: never use it alone to authorize a change.

- **address** (required) `string`: Identifier of the sender on the channel: an email address for `EMAIL`, a phone number in E.164 format for `WHATSAPP` and `SMS`, the user identifier of the channel otherwise. Masked as `[EMAIL]`, `[PHONE]` or `[ID]` according to `channel`. `null` once the reply is past its retention of 12 months after `received_at`. (example: "[EMAIL]")
- **name** (required) `string`: Display name of the sender, when the channel carries one. `null` otherwise, and once the reply is past its retention of 12 months after `received_at`. (example: "Laura Gómez")

## InvoiceReplyAttachment

An attachment of the reply, with its file name.

- **id** (required) `string` (uuid): Identifier of the attachment, stable across reads. (example: "5b0e2c7a-91d4-4f3e-8a6b-2c1d9e0f7a34")
- **url** (required) `string` (uri-reference): Relative URL of the attachment resource. Relative to the API base URL (e.g., https://app.beel.es/api). Note it is a link to a link: reading it returns a temporary download link, or `download_url: null` when there is no file or it has expired. (example: "/v1/companies/9f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f/invoice-replies/3f0c9a1e-6b2d-4c8f-a1e5-7d9b0c2e4f61/attachments/5b0e2c7a-91d4-4f3e-8a6b-2c1d9e0f7a34")
- **file_expires_at** (required) `string` (date-time): Estimate of when the file stops being available. `null` when the attachment has no downloadable file, as with those registered with `POST .../invoice-replies`. (example: "2026-11-18T10:15:00Z")
- **content_type** (required) `string`: Media type declared by the channel. (example: "application/pdf")
- **size_bytes** (required) `integer` (int64): Size of the file; `null` when the channel does not report it. (example: 48213)
- **filename** (required) `string`: Name of the file; `null` when the channel gives none, as with a photo. (example: "justificante-transferencia.pdf")

## InvoiceReplyAttachmentSummary

An attachment of the reply. BeeL. does not store the file: a temporary download link is requested when you read the attachment at its `url`.

- **id** (required) `string` (uuid): Identifier of the attachment, stable across reads. (example: "5b0e2c7a-91d4-4f3e-8a6b-2c1d9e0f7a34")
- **url** (required) `string` (uri-reference): Relative URL of the attachment resource. Relative to the API base URL (e.g., https://app.beel.es/api). Note it is a link to a link: reading it returns a temporary download link, or `download_url: null` when there is no file or it has expired. (example: "/v1/companies/9f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f/invoice-replies/3f0c9a1e-6b2d-4c8f-a1e5-7d9b0c2e4f61/attachments/5b0e2c7a-91d4-4f3e-8a6b-2c1d9e0f7a34")
- **file_expires_at** (required) `string` (date-time): Estimate of when the file stops being available. `null` when the attachment has no downloadable file, as with those registered with `POST .../invoice-replies`. (example: "2026-11-18T10:15:00Z")
- **content_type** (required) `string`: Media type declared by the channel. (example: "application/pdf")
- **size_bytes** (required) `integer` (int64): Size of the file; `null` when the channel does not report it. (example: 48213)


---

Full OpenAPI spec: https://docs.beel.es/api/openapi