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 or Register only.
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. 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. 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.
- You need the signers: either a saved signature flow 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.
curl -X POST https://www.digiploma.com.br/api/degrees \
-H "X-Api-Key: $API_KEY" -H "Content-Type: application/json" \
-d @degree.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). 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); andisSegundaViafor a second copy.degreeType:Default,Nsf(MEC's schema variant for the NSF layout) orJudicialDecision(diploma issued by court order).isNsfis obsolete; usedegreeType.visualRepresentationFieldsContent: optional texts that replace the values of named form fields in the RVDD.
A complete example is in the JSON sample file, and the full schema is in the API reference. 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, and Signatures and Lacuna Signer shows who signs what, with diagrams.
The response
{ "success": true, "id": "9b0f…", "academicTranscriptId": "2c4e…", "errors": null }
success, not just the HTTP statusFailures 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.
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.
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 of both files.
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.
{ "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.
reasonThe 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. Annulled diplomas appear in the institution's list of annulled diplomas.
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:
| Parameter | Filter |
|---|---|
Status | Diplomas in this status. |
BatchId | Diplomas created by this batch. |
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, 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 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}/validationis the public validation, which needs no API key. See Public 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 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 |