---
title: "Submit the signed representation document"
method: POST
path: "/v1/companies/{company_id}/representation/submit"
tags: ["CompanyRepresentation"]
---

# Submit the signed representation document

`POST /v1/companies/{company_id}/representation/submit`

## Request

- Base URL: `https://app.beel.es/api`
- URL: `https://app.beel.es/api/v1/companies/{company_id}/representation/submit`
- Auth: HTTP bearer

Uploads the digitally signed representation PDF of a company, sent as
`multipart/form-data` in the `file` field.

- **Validation:** the signature is checked with the provider within this call, so a
  rejected signature answers `400 PDF_SIGNATURE_INVALID`. Poll
  `GET /v1/companies/{company_id}/representation` for the resulting state.

## Headers

- `Idempotency-Key` string

## Response `200`

Signed document submitted for validation

- RepresentationActionResponse
  - `success` boolean
  - `data` object
    - `status` string
    - `message` string
  - `meta` ResponseMeta
    - `timestamp` string, date-time
    - `request_id` string

## Other responses

- `400`: The signed document was not accepted. Nothing changed. Branch on `error.code`: * `SIGNING_ONLY_IN_LIVE` — the request runs in Test (a `beel_sk_test_*` key or the `BeeL-Environment: sandbox` header). The document is signed with a real certificate and registered with the real AEAT, so it is only accepted in Live. * `NIF_NOT_CONFIGURED` — the company has no NIF to sign for. * `PDF_EMPTY` — the `file` field is empty. * `PDF_TOO_LARGE` — the file is over 10 MB. A request over 12 MB is cut earlier with `413`. * `PDF_INVALID_EXTENSION` — the file name does not end in `.pdf`. * `PDF_INVALID_FORMAT` — the content is not a PDF. * `NO_UNSIGNED_DOCUMENT` — there is no generated, unsigned document to sign. Generate it with `POST /v1/companies/{company_id}/representation` first. * `PDF_SIGNATURE_INVALID` — the provider rejected the signature. `error.message` carries the reason when the AEAT gave one. * `PDF_VALIDATION_FAILED` — the provider could not be reached to check the signature. Repeat the request later.
- `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.
- `403`: Your account does not own or manage this company, or does not hold write access over it. That case answers `error.code` `ACTIVE_COMPANY_NOT_ACCESSIBLE`.
- `413`: Payload too large. On this operation that normally means an uploaded file exceeded its own limit (`FILE_TOO_LARGE`). Any request may also be rejected with `REQUEST_BODY_TOO_LARGE` when the body as a whole exceeds the maximum described under *Request body size*. In both cases the `details` object carries the applicable maximum, except when the HTTP connector cuts the request first, which carries no `details`.
- `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.
- `500`: Internal server error
- `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.

---

[API](https://skmtc.dev/beel/apis/beel-public-api.md) · [All operations](https://skmtc.dev/beel/apis/beel-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/beel/apis/beel-public-api/revisions/ffbc0ae31f79?raw)
