---
title: "Digiploma API"
description: "Overview of the Digiploma REST API: what it covers, where the Swagger reference is and which guide to start with for each organization type."
canonical: "https://docs.lacunasoftware.com/en-us/articles/digiploma/api"
locale: "en"
product: "Digiploma"
last_updated: "2026-10-12"
---

# Digiploma API

Digiploma has a REST API, with JSON requests and responses, that covers what the web application does: create diplomas, academic
transcripts and curriculums, follow their signatures, download their files, validate them, and keep the documents MEC requires.

The **API reference**, with every operation and model, is published by each instance at `/swagger`; for the cloud service, at
[www.digiploma.com.br/swagger](https://www.digiploma.com.br/swagger/). These pages explain how the operations fit together. The examples use
`https://www.digiploma.com.br`; for an [on-premises](https://docs.lacunasoftware.com/en-us/articles/digiploma/on-premises) instance, use its address instead.

## Choose your integration

What you can do depends on the **type of your organization** in Digiploma:

| If your institution… | Organization type | Start with |
|---|---|---|
| Issues and registers its own diplomas | Emissora e Registradora | [Issue and register](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/degrees) |
| Issues diplomas that another institution registers | Emissora | [Issue only](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/emissions) |
| Registers diplomas issued by other institutions | Registradora | [Register only](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/registrations) |

Issuers can also create [academic transcripts](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/academic-transcripts) and [curriculums](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/curriculums). In every case you will use
[templates and signature flows](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/templates-and-flows), and probably [batches](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/batches) and [webhooks](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/webhooks). Registrars also
publish the [lists of annulled diplomas](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/cancellation-lists), and institutions produce [inspection files](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/inspection-files) for MEC.
Anyone can [validate a document](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/validation). An operation that the organization's type does not allow fails with
`SubscriptionOperationNotAllowed`.

The signatures are collected by Lacuna Signer, so the organization needs a Signer API key set in its **Configurações** (Settings) before
it creates documents. See [Signer integration setup](https://docs.lacunasoftware.com/en-us/articles/digiploma/on-premises/signer-setup).

## Authentication

Every call needs an **API key**, sent in the `X-Api-Key` header, except the [public validation](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/validation) operations, which need
none:

```text
X-Api-Key: your-app|0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0
```

API keys belong to **applications**, which the instance administrator creates in **Sys Admin** → **Aplicações** (Applications), choosing
the organization and the application's roles (**Papéis**). To get a key, ask the administrator of the instance. Each key works only in
its application's organization: it can only see and create documents of that organization. The key is shown only once, when it is
created, so store it in a secret manager.

A missing or invalid key gets `401`. A key whose roles lack the permission for an operation gets `403`.

### Permissions

What an application can do depends on its roles:

| Role | Can |
|---|---|
| **Administrador** | Everything in the organization, including its settings, its webhook and its applications. |
| **Gerente** | Everything in the organization, except changing its settings, its webhook and its applications. |
| **Operador** | Create and update documents, batches, templates and flows. It cannot annul diplomas, replace visual representations, delete templates and flows, or manage institutions. |
| **Monitor** | Read only. |

The roles **Integração de Emissão** and **Integração de Registro** are created automatically for the integration between two Digiploma
instances; do not assign them to your applications.

## Conventions

* JSON property names are in camelCase. The MEC data keeps the Portuguese names of the MEC XML schema, such as `dadosDiploma` and
  `iesEmissora`.
* Enumerations are written as their names, such as `"Active"`.
* Ids are GUIDs. Dates are in ISO 8601 format; dates read from the database come back in UTC.
* Error messages are in Portuguese.

### Pagination

Operations that list items take these query parameters:

| Parameter | Description |
|---|---|
| `Q` | Text to search. What it matches depends on the operation. |
| `Limit` | Number of items to return. Default: 10. |
| `Offset` | Number of items to skip (not a page number). Default: 0. |
| `Order` | `Asc` (default) or `Desc`. The field it sorts by depends on the operation. |

The response has the items of the page and the total number of items that match:

```json
{ "items": [ … ], "totalCount": 1234, "nextCursor": null }
```

`nextCursor` is not used: page with `Offset`.

### Uploads

Operations that take a file, such as a batch file or a template, refer to an **upload**: send the file first, then use the upload's `id`.
There are two ways to send it:

* `POST /api/uploads`, as `multipart/form-data`, with the file in a part named `file` and its type in a text field named `contentType`
  (and, optionally, its name in `name`):

    ```bash
    curl -X POST https://www.digiploma.com.br/api/uploads -H "X-Api-Key: $API_KEY" \
      -F "file=@formandos.json" -F "contentType=application/json" -F "name=formandos.json"
    ```

    The response is `{ "id": "…", "name": "formandos.json", "contentType": "application/json", "location": "…" }`.

* `POST /api/uploads/bytes`, as JSON, with the file in Base64: `{ "bytes": "…" }`. The response is `{ "id": "…", "size": …, "digest": "…" }`.

Then refer to the upload with its `id`, `name` and `contentType` (required), as in:

```json
"batchFile": { "id": "5d3b…", "name": "formandos.json", "contentType": "application/json" }
```

Use the upload right away: uploaded files can be deleted after a day. The accepted types include PDF (`application/pdf`), XML (`application/xml`,
`text/xml`), JSON (`application/json`), CSV (`text/csv`) and images; when you send `name`, its extension must match the type.

### Downloads and tickets

Most files can be downloaded in three ways:

| Operation | Returns |
|---|---|
| `…/xml`, for example | The file itself. |
| `…/xml-b64` | JSON with the file in Base64: `{ "bytes": "…", "name": "…", "contentType": "…" }`. |
| `…/xml-ticket` | A **ticket**: `{ "location": "…", "filename": "…" }`. |

A ticket's `location` is a temporary address to download the file **without the API key**, for example to pass to a browser. It may be a
path relative to the instance, such as `/api/degrees/…/xml/file?access_ticket=…`: in that case, prefix it with the instance address. Tickets
expire after a short time (about an hour), so get one right before the download. Conditions such as "the document must be signed" are
checked when the file is downloaded, not when the ticket is issued.

## Creation results

The operations that create a single document (`POST /api/degrees`, `/api/emissions`, `/api/academic-transcripts` and `/api/curriculums`)
and `POST /api/emissions/{id}/degree-xml` report problems in two ways:

* Problems found **before** the document is generated, such as a missing template, an invalid flow or a missing Signer key, return an
  error status, as any other operation.
* Problems found **while** it is generated, such as data rejected by the MEC XML schema, a duplicate, or an error in Signer, return
  **HTTP 200** with `"success": false`, and a description in `errors`.

```json
{ "success": false, "id": null, "errors": "2026-10-11 14:02:11.532 -03:00 … Erro: …" }
```

Always check `success`. `errors` is a processing log in Portuguese, meant for people, not for parsing.

## Errors

| Status | Meaning |
|---|---|
| `400` | The request is malformed, for example a required field is missing. The body lists the invalid fields in `errors`. |
| `401` | The API key is missing or invalid. |
| `403` | The API key cannot perform this operation, or access this item. |
| `422` | The request breaks a business rule, **or refers to an item that does not exist**. The body is an `ErrorModel`. |

```json
{ "code": "DegreeNotFound", "message": "Diploma não encontrado", "details": { "id": "9b0f…" } }
```

`code` identifies the error; `message`, in Portuguese, is meant for people and may change; `details` has data about the error, when
available. Handle errors by `code`. The codes are listed in the API reference (`ErrorCodes`), and new ones may be added. The most common:

| Code | Meaning |
|---|---|
| `…NotFound` (such as `DegreeNotFound`, `TemplateNotFound`) | The item does not exist. |
| `SubscriptionOperationNotAllowed` | The organization's type does not allow the operation. |
| `SignerApiKeyNotSet`, `SignerApiKeyError` | The organization has no Signer API key, or Digiploma could not reach Signer with it. |
| `TemplateTypeNotExpected` | The template is of another document type. |
| `DocumentFlow…` | The signature flow breaks the rules of its type. See [Signature flows](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/templates-and-flows#signature-flows). |
| `ValidationCodeDuplicated` | Another document, not canceled, has the same validation code. |
| `…NotValid`, `…NotSigned` | The document is not active, or not signed yet. |
| `…InvalidStatus`, `…CannotBe…` | The operation is not allowed in the item's current status. |
| `InvalidCaptcha`, `InvalidOperationCaptchaEnabled` | See [Public validation](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/validation#captcha). |
