---
title: "Issue and register diplomas"
description: "How institutions of type Emissora e Registradora issue and register their own diplomas in Digiploma: XML files, signatures, RVDD and final transcript."
canonical: "https://docs.lacunasoftware.com/en-us/articles/digiploma/api/degrees"
locale: "en"
product: "Digiploma"
last_updated: "2026-10-11"
---

# Issue and register diplomas

This page is for institutions that **issue and register** their own diplomas in the same Digiploma organization, of type
**Emissora e Registradora** (issuer and registrar). Digiploma assumes the institution has already completed both steps internally, and uses
the API to formalize them as MEC requires: it generates the XML files, collects the signatures in Lacuna Signer, and produces the visual
representation and the final academic transcript.

If your institution only issues or only registers diplomas, see [Issue only](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/emissions) or [Register only](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/registrations).

## What a diploma is made of

| Part | What it is |
|---|---|
| **Diploma XML** | The public data of the diploma (`DadosDiploma` and `DadosRegistro`), signed in three stages: issuing, registration and storage. It is the file the public validation returns. |
| **Academic documentation XML** | The private data used to register the diploma: the student's personal data, the academic record and the supporting documents (`documentacaoComprobatoria`). Signed by the issuer. |
| **RVDD** | The visual representation of the digital diploma, a PDF filled from a [diploma template](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/templates-and-flows#templates). If the template also has a letterhead version, a second PDF is produced for printing on letterhead paper. |
| **Final academic transcript** | A separate document, generated with the diploma. See [Academic transcripts](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/academic-transcripts). Not generated for a second copy (*segunda via*) or a diploma issued by judicial decision. |

## Before you start

* The organization must be of type **Emissora e Registradora**. Otherwise the call fails with `SubscriptionOperationNotAllowed`.
* The Signer API key must be set in the organization's **Configurações** (Settings). Otherwise the call fails with `SignerApiKeyNotSet`.
* You need a **diploma template** and an **academic transcript template**. See [Templates](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/templates-and-flows#templates).
* You need the signers: either a saved [signature flow](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/templates-and-flows#signature-flows) of type `EmissionRegistration`, or the
  signers inline in each request.

## Create a diploma

`POST /api/degrees` creates one diploma. To create many at once from a JSON or CSV file, use a [batch](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/batches).

```bash
curl -X POST https://www.digiploma.com.br/api/degrees \
  -H "X-Api-Key: $API_KEY" -H "Content-Type: application/json" \
  -d @degree.json
```

```json
{
  "templateId": "0f8b1c2e-…",
  "academicTranscriptTemplateId": "6a1d9e44-…",
  "documentFlowId": "c2f0e7a1-…",
  "newFolderName": "Formandos 2026-1",
  "degree": {
    "degreeType": "Default",
    "diploma": {
      "dadosDiploma": { "diplomado": { … }, "dadosCurso": { … }, "iesEmissora": { … }, "dataConclusao": "2026-06-30", … },
      "dadosRegistro": { "iesRegistradora": { … }, "livroRegistro": { … }, … }
    },
    "documentacaoAcademica": {
      "registro": { "dadosPrivadosDiplomado": { … }, "documentacaoComprobatoria": [ … ], "isSegundaVia": false }
    }
  }
}
```

| Field | Required | Description |
|---|---|---|
| `templateId` | Yes | The diploma template used to build the RVDD. |
| `academicTranscriptTemplateId` | Yes | The academic transcript template used to build the transcript's visual representation. Required even for a second copy or a judicial-decision diploma, which generate no transcript. |
| `degree` | Yes | The MEC data of the diploma (see below). |
| `documentFlowId` | One of the two | A saved signature flow of type `EmissionRegistration`. |
| `documentFlow` | One of the two | The signers inline (see [Signers](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/degrees#signers)). Takes precedence over `documentFlowId`. |
| `newFolderName` | No | Creates a Signer folder with this name for the documents. Takes precedence over `signerFolderId`. |
| `signerFolderId` | No | An existing Signer folder for the documents. Without either folder field, the documents go to the root of the organization in Signer. |

The `degree` object mirrors the MEC XML schema, with the Portuguese element names of Portaria MEC 554/2019:

* `diploma.dadosDiploma`: the graduate (`diplomado`), the course (`dadosCurso`), the issuing institution (`iesEmissora`), the completion date
  and, when applicable, the judicial-decision statements and the original institution of an assisted transfer.
* `diploma.dadosRegistro`: the registering institution (`iesRegistradora`), the registration book data (`livroRegistro`: book, page,
  sequence and registration numbers, dates, person responsible) and additional information.
* `documentacaoAcademica.registro`: the graduate's private data, including parentage and the academic record (`historico`), which also feeds
  the final academic transcript; the statement of responsibility (`termoResponsabilidade`); the supporting documents
  (`documentacaoComprobatoria`, each one a PDF/A in Base64); and `isSegundaVia` for a second copy.
* `degreeType`: `Default`, `Nsf` (MEC's schema variant for the *NSF* layout) or `JudicialDecision` (diploma issued by court order).
  `isNsf` is obsolete; use `degreeType`.
* `visualRepresentationFieldsContent`: optional texts that replace the values of named form fields in the RVDD.

A complete example is in the [JSON sample file](https://www.digiploma.com.br/assets/files/json-template5.json), and the full schema is in the
[API reference](https://www.digiploma.com.br/swagger/). The data is validated against the MEC XML schemas before the documents are created.

### Signers

Each diploma goes through four signing stages. When you send `documentFlow` instead of a saved flow, all four must be filled, or the call
fails with `DocumentFlowInvalidEmissionRegistrationData`:

| Stage | Field | Rules |
|---|---|---|
| Issuing (*Emissão*) | `issuingFlow` | At least one representative of the issuer (e-CPF) **and** the issuer itself (e-CNPJ). |
| Registration (*Registro*) | `registrationFlow` | Representatives of the registrar only (e-CPF). |
| Storage (*Armazenamento*) | `storageFlow` | Exactly one institutional signature (e-CNPJ), with `requiredSignatures` = 1. |
| Academic transcript | `academicTranscriptFlow` | At least one institutional signature (e-CNPJ). |

The diploma XML is signed by the issuing, registration and storage stages, in that order. The academic documentation XML is signed by the
issuing stage, followed by a signature of the issuer's e-CNPJ. The academic transcript is a separate Signer document, signed by its own
stage. The structure of each stage is described in [Signature flows](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/templates-and-flows#signature-flows), and
[Signatures and Lacuna Signer](https://docs.lacunasoftware.com/en-us/articles/digiploma/signatures) shows who signs what, with diagrams.

### The response

```json
{ "success": true, "id": "9b0f…", "academicTranscriptId": "2c4e…", "errors": null }
```

> **Warning: Check success, not just the HTTP status**
>
> Failures that happen while the documents are being generated, such as data rejected by the MEC XML schema or an error in Signer, return
> **HTTP 200** with `"success": false`. `errors` then holds the processing log in Portuguese, including the schema errors. Only the checks
> done before generation (organization type, Signer key, templates, flow) and a duplicate validation code return an error status. See
> [Creation results](https://docs.lacunasoftware.com/en-us/articles/digiploma/api#creation-results).

If the academic transcript cannot be generated, the diploma is still created: `success` is `true` and `academicTranscriptId` is `null`. The
reason is in the `academicTranscriptCreationError` field of the `DegreeCreated` [webhook](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/webhooks).

### The validation code

Digiploma computes the diploma's **validation code** (*código de validação*) from its data, in the format
`{issuer MEC code}.{registrar MEC code}.{12 hexadecimal characters}`, and writes it into the diploma XML. You cannot supply it. A second
diploma with the same code is refused with `ValidationCodeDuplicated` while the first one is not canceled.

## Signing and statuses

After the diploma is created, Signer collects the signatures, and notifies Digiploma as each document is concluded.

| `status` | Meaning |
|---|---|
| `Created` | Created; waiting for signatures. |
| `Active` | The diploma XML is signed: the diploma is valid. |
| `CanceledTemporarily` | Temporarily annulled (*anulado temporariamente*). Can be restored. |
| `Canceled` | Annulled (*anulado*). |

Two flags complete the status: `isSigned` (diploma XML signed) and `isAcademicDocumentationSigned` (academic documentation XML signed). A
diploma becomes `Active` as soon as its diploma XML is signed, and is **concluded** when both XML files are signed, in whichever order. Only
then does Digiploma send the `DegreeConcluded` webhook and schedule the [restamping](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/restamps) of both files.

> **Note**
>
> Between those two moments, `GET /api/degrees/{id}/xml` already returns the diploma XML, but the public validation still reports the
> diploma as not valid, because it requires both files to be signed.

## Annul, suspend or restore a diploma

`POST /api/degrees/{id}/status` changes the status of a diploma. It requires the `UpdateDegree` permission, which the **Operador**
(Worker) and **Monitor** roles do not have. See [Permissions](https://docs.lacunasoftware.com/en-us/articles/digiploma/api#permissions).

```json
{ "status": "Canceled", "cancellationReason": "ErroDeFato", "reason": "Nome do diplomado grafado incorretamente" }
```

| Field | Description |
|---|---|
| `status` | `Canceled`, `CanceledTemporarily` or `Active` (restore). |
| `cancellationReason` | The reason for the annulment, required when annulling a diploma whose two XML files are signed: `ErroDeFato`, `ErroDeDireito`, `DecisaoJudicial`, `ReemissaoParaComplementoDeInformacao`, `ReemissaoParaInclusaoDeHabilitacao` or `ReemissaoParaAnotacaoDeRegistro`. |
| `reason` | A free-text note, up to 500 characters. |

| From | To | What happens |
|---|---|---|
| `Created` | `Canceled` | The pending documents are **deleted** from Signer. The diploma can never be restored. |
| `Active` | `Canceled` | The diploma is annulled. `cancellationReason` is required if both XML files are signed. |
| `Active` | `CanceledTemporarily` | The diploma is suspended. Nothing changes in Signer. |
| `CanceledTemporarily` | `Active` | The diploma is restored. Both XML files must be signed (`DegreeNotSignedCannotBeRestored`), and no other valid diploma may have the same validation code (`DegreeCannotRestoreValidAlreadyExists`). |
| `CanceledTemporarily` | `Canceled` | The diploma is annulled. |

Any other change fails with `DegreeInvalidStatus`. A `Canceled` diploma cannot be restored directly.

> **Warning: Always send reason**
>
> The webhook for a status change (`DegreeCanceled`, `DegreeCanceledTemporarily` or `DegreeRestored`) is sent only when the change has a
> reason text. Annulling a signed diploma always has one, built from `cancellationReason`. A suspension, a restore, or an annulment before the
> signatures are complete sends **no webhook** unless you fill `reason`.

Changing the status of a diploma does not change its academic transcript, which has its own
[status operations](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/academic-transcripts#cancel-suspend-or-restore). Annulled diplomas appear in the institution's
[list of annulled diplomas](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/cancellation-lists).

## Read diplomas

| Operation | Returns |
|---|---|
| `GET /api/degrees/{id}` | The diploma's metadata: student, course, institutions, status, signing flags, validation code, Signer document ids and links, and the linked academic transcript. The cheapest call. |
| `GET /api/degrees/{id}/information` | The public data (`dadosDiploma`, `dadosRegistro`) read from the diploma XML. Works in any status. |
| `GET /api/degrees/{id}/academic-documentation` | The academic documentation read from the signed XML, including the supporting documents as Base64 PDFs, so it can be large. Fails with `DegreeAcademicDocumentationNotSigned` until that XML is signed. |
| `GET /api/degrees/{id}/history` | The status changes, newest first, as `{status, reason, date}`. |
| `GET /api/degrees` | A page of diplomas with the full model. |
| `GET /api/v2/degrees` | A page of diplomas with only `id`, `studentName`, `studentSocialName`, `studentCpf`, `course`, `creationDate`, `updateDate` and `status`. Faster for large volumes. |

Both list operations take the same parameters, besides the [paging parameters](https://docs.lacunasoftware.com/en-us/articles/digiploma/api#pagination):

| Parameter | Filter |
|---|---|
| `Status` | Diplomas in this status. |
| `BatchId` | Diplomas created by this [batch](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/batches). |
| `StartDateUtc`, `EndDateUtc` | Diplomas **created** from `StartDateUtc` (inclusive) until `EndDateUtc` (exclusive). |
| `IsSigned` | `true` returns diplomas with at least one signed XML file, in any status other than `Created`. `false` does not filter. |
| `Q` | Text in the student's CPF, name or social name, or in the course name. Punctuation is ignored, so a formatted CPF also matches. It does not search the validation code. |

Results are sorted by **update** date (`Order`: `Asc` by default, or `Desc`).

## Download the files

Each file can be downloaded in three ways: as the file itself, as JSON with the content in Base64 (`{bytes, name, contentType}`), or as a
[ticket](https://docs.lacunasoftware.com/en-us/articles/digiploma/api#downloads-and-tickets), a temporary URL that does not need the API key.

| Document | Direct download | Base64 | Ticket | Available when |
|---|---|---|---|---|
| Diploma XML | `GET /{id}/xml` | `GET /{id}/xml-b64` | `GET /{id}/xml-ticket` | The diploma is `Active` (`DegreeNotValid` otherwise). For a ticket, checked when it is downloaded. |
| Academic documentation XML | `GET /{id}/academic-documentation-xml` | `GET /{id}/academic-documentation-xml-b64` | `GET /{id}/academic-documentation-ticket` | That XML is signed, in any status. |
| RVDD | — | `GET /{id}/visual-representation-b64` | `GET /{id}/visual-representation-ticket` | Always. |
| Letterhead RVDD | — | — | `GET /{id}/letterhead-visual-representation-ticket` | The template has a letterhead version (`hasLetterhead`). Otherwise the download fails with `LetterheadNotFound`. |

All paths are relative to `/api/degrees`.

## Replace the visual representation

`POST /api/degrees/{id}/visual-representation` replaces the RVDD of a diploma that is `Created` or `Active`. The signed XML files are not
affected. It requires the `UpdateDocumentVisualRepresentation` permission (**Administrador** and **Gerente** roles).

| Field | Description |
|---|---|
| `templateId` | Regenerates the RVDD from another diploma template. Takes precedence over `uploadId`. |
| `fieldsContent` | With `templateId`, texts that replace the values of named form fields. |
| `uploadId` | Replaces the RVDD with an [uploaded](https://docs.lacunasoftware.com/en-us/articles/digiploma/api#uploads) PDF, which must have exactly two pages, the first one in landscape (`InvalidNumberOfPages`, `InvalidPageOrientation`). |

## Generate the academic transcript later

If a diploma has no academic transcript, `POST /api/degrees/{id}/academic-transcript` generates its **final** academic transcript from the
diploma's data. The body takes `academicTranscriptTemplateId`, the signers (`documentFlow` with `academicTranscriptFlow`, or
`documentFlowId`) and, optionally, `signerFolderId` or `newFolderName`. It returns the transcript, and fails with
`DegreeAlreadyHasLinkedAcademicTranscript` if the diploma already has one, or `DegreeTypeNotSupported` for a second copy or a
judicial-decision diploma. Unlike the other ways of creating a transcript, this one sends no `AcademicTranscriptCreated` webhook.

## Validate a diploma

* `GET /api/degrees/codes/{code}` validates a diploma of your own organization by its validation code, with the API key, and returns the CPF
  unmasked.
* `GET /api/degrees/{code}/validation` is the **public** validation, which needs no API key. See [Public validation](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/validation).

## Webhooks

| Event | When |
|---|---|
| `DegreeCreated` | The diploma was created. Carries `academicTranscriptCreationError` when the transcript could not be generated. |
| `DegreeConcluded` | Both XML files are signed. |
| `DegreeCanceled`, `DegreeCanceledTemporarily`, `DegreeRestored` | The status changed, with a reason (see above). |

See [Webhooks](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/webhooks) for the payloads.

## Operation reference

| Operation | Description |
|---|---|
| `POST /api/degrees` | Create a diploma |
| `GET /api/degrees` | List diplomas |
| `GET /api/v2/degrees` | List diplomas (compact model, for large volumes) |
| `GET /api/degrees/{id}` | Get a diploma |
| `GET /api/degrees/{id}/information` | Get the public data of a diploma |
| `GET /api/degrees/{id}/academic-documentation` | Get the academic documentation data |
| `GET /api/degrees/{id}/history` | Get the status history |
| `POST /api/degrees/{id}/status` | Annul, suspend or restore a diploma |
| `GET /api/degrees/{id}/xml`, `…/xml-b64`, `…/xml-ticket` | Download the diploma XML |
| `GET /api/degrees/{id}/academic-documentation-xml`, `…/academic-documentation-xml-b64`, `…/academic-documentation-ticket` | Download the academic documentation XML |
| `GET /api/degrees/{id}/visual-representation-b64`, `…/visual-representation-ticket` | Download the RVDD |
| `GET /api/degrees/{id}/letterhead-visual-representation-ticket` | Download the letterhead RVDD |
| `POST /api/degrees/{id}/visual-representation` | Replace the RVDD |
| `POST /api/degrees/{id}/academic-transcript` | Generate the final academic transcript of a diploma |
| `GET /api/degrees/codes/{code}` | Validate a diploma of your organization |
| `GET /api/degrees/{code}/validation`, `…/validation/visual-representation`, `…/validation/xml` | [Public validation](https://docs.lacunasoftware.com/en-us/articles/digiploma/api/validation) |
