Case types
What kind of case a set of documents makes up, the manifest, master data, ZIP packages and the grant_settlement contract
A case type tells Aletheia what kind of case a set of documents makes up: which document roles it has, whether documents are grouped into items, and which checks run.
| Case type | What it is | Status |
|---|---|---|
account_application | An account or loan application: ID, payslips, bank statement, pension notice. The default. | Live |
grant_settlement | A grant settlement: one application plus cost items, each with invoice(s), payment proof(s) and service description(s). | Intake and routing live; checks arrive in later releases |
Nothing changes if you do not send a case type. A request without case_type runs as
account_application, exactly as before, with the same findings and verdict. Every response
also carries case_type and a few new keys that are null for account_application, see
Response. Clients must ignore unknown response fields.
Which case types you may use is set per tenant. Ask your IDCanopy contact to enable one.
1. Where case_type goes
All three entry points accept the same three optional fields:
| Field | Type | Meaning |
|---|---|---|
case_type | string | account_application (default) or grant_settlement. |
manifest | object | Which uploaded file plays which role, and how files group into items (The manifest). Typed case types only. |
master_data | object | The applicant's master data that documents are checked against (Master data). Typed case types only. |
| Entry point | How to send them |
|---|---|
POST /v1/applicants | JSON body fields. The manifest can also be set later with PUT /v1/applicants/{id}/manifest. |
POST /analyze | Multipart form fields. manifest and master_data are JSON strings. |
POST /analyze/zip | Multipart form fields, as for /analyze. Or put a manifest.json in the ZIP, or use the folder convention (ZIP packages). |
case_meta is unchanged: free JSON, logged and echoed, never used for routing.
2. The manifest
The manifest assigns each uploaded file to a role. For grant_settlement:
| Role | Level | Expected count |
|---|---|---|
application | case | exactly 1 |
membership_proof | case | 0 or more |
invoice | item | 1 or more per item |
payment_proof | item | 1 or more per item (partial payments: list them all) |
service_description | item | 1 or more per item |
One item is one cost item: its invoice(s), the payment proof(s) for them, and the service description(s).
{
"application": ["application.pdf"],
"membership_proof": ["membership.pdf"],
"items": [
{
"id": "1",
"invoice": ["invoice-1.pdf"],
"payment_proof": ["payment-1a.pdf", "payment-1b.pdf"],
"service_description": ["service-1.pdf"]
},
{
"id": "2",
"invoice": ["invoice-2.pdf"],
"payment_proof": ["payment-2.pdf"],
"service_description": []
}
]
}Rules:
- Every role is a list of filenames.
- Files are referenced by filename (no folders, at most 255 characters), and a filename may
appear only once in the manifest. Item
ids must be unique and are at most 64 characters. - Filenames are compared in Unicode NFC form, so
éwritten as one or two code points is the same name. - Document names must be unique within the case. In a ZIP the name is the path inside the ZIP, so
1/invoice.pdfand2/invoice.pdfare two different documents. A manifest matches by bare filename, so with a manifest filenames must also be unique across ZIP folders. - With a manifest, the role comes from the manifest only. The filename is never used to guess a document's type.
- A file you upload but do not name in the manifest is reported as an
unassigned_documentfinding (severityINFO). It is not checked. - A file the manifest names but you never uploaded does not fail the request. Its item becomes
not_checkableand lists it undermissing, because uploads and the manifest may arrive in either order. - Unknown keys are rejected (
422), so a typo cannot silently drop a role.
3. Master data
Master data is what the documents are checked against. For grant_settlement:
{
"applicant": {
"name": "Example Trading GmbH",
"address": "Example Street 1, 1010 Vienna",
"iban": "AT611904300234573201",
"uid": "ATU12345678"
},
"application_date": "2025-11-04",
"funding_period": { "from": "2025-11-04", "to": "2027-03-31" },
"approved_target_countries": ["US", "CA"],
"approved_amount": { "value": 30000, "currency": "EUR" }
}- Every field is optional. A check that needs a field you did not send reports
not_checkableand names the field; the request is not rejected. - Dates are ISO 8601 (
YYYY-MM-DD). Country codes are ISO 3166-1 alpha-2.currencyis ISO 4217. - Master data is personal data.
POST /v1/applicantsstores it encrypted, never in plain text.POST /analyzeandPOST /analyze/zipvalidate it but do not store it. - Error responses name the invalid field but never repeat the submitted value.
4. ZIP packages
For grant_settlement, the ZIP keeps its folder structure. Aletheia decides roles in this order:
- the
manifestform field, if sent; - otherwise a
manifest.jsonat the root of the ZIP; - otherwise the folder convention.
filing.zip
application.pdf root-level files: role "application"
manifest.json optional; wins over the folders
1/ each top-level folder is one item; item id = folder name
invoice.pdf
payment.pdf
service.pdf
2/
invoice.pdf the same filename in two folders is fine without a manifest
payment.pdfWith the folder convention, each top-level folder becomes an item. In this release the documents
inside a folder are not yet given a role: they are listed as unassigned_document findings on
their item. Automatic role detection inside a folder arrives in a later release; send a manifest
if you need roles now.
A manifest.json names files by filename, so with a manifest the filenames in the ZIP must be
unique across folders.
An intake metadata.json entry at the archive root is handled as before. For
account_application, ZIPs are processed exactly as before (folders are flattened, and a
manifest.json entry is rejected as an unsupported file).
5. Response
Every ForensicResult carries these fields:
| Field | account_application | grant_settlement |
|---|---|---|
case_type | "account_application" | "grant_settlement" |
risk_indicator | null | none, review or high |
consistency_result | null | match, mismatch or not_checkable (case roll-up) |
items | null | one entry per manifest item or folder |
missing | null | case-level inputs the checks needed but did not get (since 0.5.1) |
Each finding has three fields that are null on account_application:
| Field | Meaning |
|---|---|
code | External code for the finding in this case type. |
item_id | The item the finding belongs to; null means case level. |
references | Other occurrences the finding points to: [{applicant_id, item_id, document}]. |
verdict, findings, advisory_score and the other existing fields keep their meaning.
Example: grant_settlement in this release
The grant checks are not enabled yet. Documents are accepted, assigned to roles and run through
the document-integrity stages (file format, PDF metadata). Findings from those stages are listed
(with their engine check_id, code: null until the checks are enabled), but in this release
they do not change the indicator or the verdict: every item is not_checkable, the indicator is
review, and the verdict is PENDING with an explanation:
{
"applicant_id": "filing-0042",
"case_type": "grant_settlement",
"verdict": {
"verdict": "PENDING",
"reason_codes": ["CASE_TYPE_CHECKS_NOT_ENABLED"],
"override_rules_fired": [],
"verdict_explanation": "Grant settlement: documents were received and passed through the quality gate and metadata stages. The case-type consistency and fraud checks are not enabled yet, so the case cannot be assessed."
},
"risk_indicator": "review",
"consistency_result": "not_checkable",
"items": [
{
"item_id": "1",
"consistency_result": "not_checkable",
"risk_indicator": "review",
"finding_refs": [1],
"missing": ["documents.service_description[service-1.pdf]"],
"documents": {
"invoice": ["invoice-1.pdf"],
"payment_proof": ["payment-1a.pdf", "payment-1b.pdf"]
}
}
],
"findings": [
{
"check_id": "unassigned_document",
"check_category": "case_type",
"severity": "INFO",
"summary": "Document notes.pdf is not assigned to a role and was not checked.",
"source_document_id": "notes.pdf",
"code": "IN-01",
"item_id": null,
"references": null
},
{
"check_id": "manifest_document_missing",
"check_category": "case_type",
"severity": "INFO",
"summary": "The manifest names documents.service_description[service-1.pdf], but no such file was uploaded.",
"source_document_id": null,
"code": "IN-02",
"item_id": "1",
"references": null
}
],
"missing": [],
"advisory_score": 96,
"advisory_band": "LOW_RISK"
}(Abridged: unchanged fields such as checker_version and analysis_ts are left out.)
items[].finding_refsare indexes intofindings.items[].missing(per item) andmissing(case level, since 0.5.1) name inputs the checks needed but did not get:documents.<role>[<filename>]: a file the manifest names was never uploaded;documents.<role>: a required role has no file at all (for example noapplication, or an item withoutservice_description);master_data.<field>: a master-data field a check needs is absent (from the checks release on).
items[].documentslists the files assigned to the item, by role, as the document ids of this case. For uploads that is the filename. For a ZIP it is the path inside the ZIP (1/invoice.pdf), even when amanifest.jsonnamed the file asinvoice.pdf. With a manifest, files are matched by filename, so in a ZIP with a manifest no two files may share a filename across folders (422).checks_performedandextractedarenullforgrant_settlementin this release.advisory_scoreandadvisory_bandare informational and do not carry meaning for this case type yet.
Finding codes
Every finding a grant_settlement check emits carries a code. The full list is
machine-readable in grant_settlement.codes.json, with
German and English texts, and rendered below. Key your integration on code, not on
check_id. check_id is engine-internal and may change; codes do not.
The two intake findings carry codes too: IN-01 (unassigned_document, a file not assigned to a
role) and IN-02 (manifest_document_missing, a file the manifest names but that was never
uploaded). Both are INFO. Before 0.5.1 they had code: null.
Texts. The code list holds the canonical German and English text for every code; for partner
output (for example an XML explanation), take the text for the finding's code from it.
findings[].message is the operator text (what and what_to_do) from the
message catalogue, English by default, with tenant-
and locale-specific overrides where agreed. It is populated for every finding, including IN-01 and
IN-02.
Why is an item not_checkable? Look at verdict.reason_codes and missing:
CASE_TYPE_CHECKS_NOT_ENABLEDinreason_codes: the checks are not enabled for this release. This takes precedence.- otherwise, the entries in
items[].missingandmissingname the inputs the checks lacked.
missing vs documents. missing names a file the way the manifest named it
(documents.invoice[invoice-1.pdf]), because no such document was received. documents lists
documents that were received, by their document id (for a ZIP, the path inside it).
Columns of the code list:
| Column | Meaning |
|---|---|
| Group | Only consistency findings decide consistency_result. consistency and fraud findings feed risk_indicator. intake findings (INFO) report how the documents were received. |
| Level | Where the rule looks: one document, one item, the whole case, or other filings (cross_case, with references pointing at them). A finding on a document or a cross-case match sets item_id to the item the document belongs to; it is null only for documents with case-level roles and for case-level rules. |
| Severity | The default findings[].severity. A tenant may override it. |
| retired | The code is never emitted. It is kept so that existing code tables stay valid, and the note names the code that covers it. |
| optional | Emitted only when the optional proof-of-service checks are enabled for the tenant. |
| assessment | A reasoned plausibility assessment, not a rule hit. It can raise risk_indicator to review at most, never to high. |
Case type grant_settlement, code list version 1.1.1. Source: grant_settlement.codes.json.
| Code | Group | Level | Severity | Text (en) | Text (de) | Notes |
|---|---|---|---|---|---|---|
IN-01 | intake | document | INFO | The document is not assigned to a role and was not checked. | Dokument ist keiner Rolle zugeordnet und wurde nicht geprüft. | |
IN-02 | intake | document | INFO | The manifest names a document that was not submitted. | Das Manifest nennt ein Dokument, das nicht übermittelt wurde. | |
UP-01 | consistency | item | MEDIUM | The invoice date is outside the approved funding period. | Rechnungsdatum liegt außerhalb des genehmigten Förderzeitraums. | |
UP-01a | consistency | item | INFO | The invoice date is before the application date. | Rechnungsdatum liegt vor dem Datum der Antragstellung. | |
UP-02 | consistency | item | MEDIUM | The invoice is not addressed to the beneficiary, and no proof of company affiliation was provided. | Rechnung ist nicht auf den Fördernehmer ausgestellt; kein Nachweis der Firmenangehörigkeit vorhanden. | |
UP-02a | consistency | item | MEDIUM | The invoice is addressed to another person, and the proof of company affiliation provided does not match. | Rechnung ist auf eine andere Person ausgestellt; vorhandener Nachweis der Firmenangehörigkeit stimmt nicht überein. | |
UP-03 | consistency | item | MEDIUM | The payer does not match the invoice recipient. | Zahlungspflichtiger stimmt nicht mit dem Rechnungsempfänger überein. | |
UP-04 | consistency | item | HIGH | The payee does not match the invoice issuer. | Zahlungsempfänger stimmt nicht mit dem Rechnungssteller überein. | |
UP-05 | consistency | item | MEDIUM | No link to an approved target country is apparent. | Kein Bezug zu einem genehmigten Zielland erkennbar. | |
UP-06 | consistency | item | MEDIUM | The payment proof cannot be matched to an invoice. | Zahlungsnachweis kann keiner Rechnung zugeordnet werden. | |
UP-06a | consistency | item | MEDIUM | The amount paid differs from the invoice amount by more than 2 %. | Bezahlter Betrag weicht um mehr als 2 % vom Rechnungsbetrag ab. | |
UP-06b | consistency | item | MEDIUM | The payment date is before the invoice date. | Zahlungsdatum liegt vor dem Rechnungsdatum. | |
UP-07 | consistency | item | MEDIUM | Incomplete cost item: an invoice, payment proof or proof of service has no counterpart. | Kostenposition unvollständig: Rechnung, Zahlungs- oder Leistungsnachweis ohne Gegenstück. | |
FD-01 | fraud | document | HIGH | The file metadata indicates later editing. | Datei-Metadaten deuten auf nachträgliche Bearbeitung hin. | |
FD-02 | fraud | document | HIGH | The visible content and the text layer of the document do not match. | Sichtbarer Inhalt und Textebene des Dokuments stimmen nicht überein. | |
FD-03 | fraud | document | HIGH | The date shown on the document is earlier than the file's creation date. | Erkennbares Belegdatum liegt vor dem Erstellungsdatum der Datei. | |
FD-04 | fraud | document | MEDIUM | Irregularities in font, layout or image structure within the document. | Auffälligkeiten in Schrift, Layout oder Bildstruktur innerhalb des Dokuments. | |
FD-05 | fraud | item | HIGH | The invoice amounts do not add up. | Rechnungsbeträge sind rechnerisch nicht schlüssig. | |
FD-06 | retired, covered by UP-06a | |||||
FD-07 | retired, covered by UP-03 | |||||
FD-08 | retired, covered by UP-04 | |||||
FD-09 | retired, covered by UP-01 | |||||
FD-10 | fraud | cross_case | HIGH | The document was submitted more than once. | Beleg wurde mehrfach eingereicht. | |
FD-11 | fraud | cross_case | CRITICAL | The invoice matches a previously submitted invoice with altered fields. | Rechnung entspricht einer bereits eingereichten Rechnung mit geänderten Feldern. | |
FD-12 | fraud | case | HIGH | One payment proof is assigned to several invoices, or one invoice is split across several items. | Zahlungsbeleg ist mehreren Rechnungen zugeordnet bzw. Rechnung ist auf mehrere Positionen verteilt. | |
FD-13 | fraud | cross_case | CRITICAL | The document was already used in another grant filing. | Beleg wurde bereits in einem anderen Förderantrag verwendet. | |
FD-14 | fraud | cross_case | HIGH | The same bank account, invoice issuer or document template recurs across several applicants. | Häufung gleicher Bankverbindung, Rechnungssteller oder Dokumentvorlage über mehrere Antragsteller. | |
FD-15 | fraud | item | HIGH | The invoice issuer's VAT ID is invalid or cannot be attributed. | UID des Rechnungsstellers ungültig oder nicht zuordenbar. | |
FD-16 | fraud | item | MEDIUM | The invoice issuer cannot be found or the information about it is contradictory. | Rechnungssteller nicht auffindbar oder widersprüchlich. | |
FD-17 | fraud | item | MEDIUM | The required type of proof of service is missing or does not fit the cost type. | Erforderliche Nachweisart zum Leistungsnachweis fehlt oder passt nicht zur Kostenart. | optional |
FD-18 | fraud | item | MEDIUM | The proof of service shows no apparent link to the invoice, funding period or target country. | Leistungsnachweis ohne erkennbaren Bezug zu Rechnung, Förderzeitraum oder Zielland. | optional; assessment |
GS-01 | consistency | case | MEDIUM | The total of the cost items exceeds the approved grant amount. | Summe der Kostenpositionen übersteigt den genehmigten Förderbetrag. |
For GS-01, invoices in other currencies are converted at the ECB reference rate of the invoice
date before the total is compared with the approved amount.
How the indicators are derived
The derivation is deterministic: rules decide, and a model never sets an indicator. This is the default; a tenant's policy may raise it, never lower it.
items[].risk_indicator is the highest of the following, over all findings with that
item_id (both groups, any level):
| Condition | risk_indicator |
|---|---|
no findings, or only INFO | none |
a LOW or MEDIUM finding, an assessment finding of any severity, or the item is not_checkable | review |
a HIGH or CRITICAL finding (not an assessment) | high |
items[].consistency_result follows these rules, in order:
mismatchif aconsistencyfinding of severityLOWor higher fired on the item.INFOfindings such as UP-01a are reported but do not change the result.not_checkableif a check lacked inputs, listed inmissing.matchotherwise.
Case level: risk_indicator and consistency_result take the worst value over all items and
the case-level findings (item_id: null, for example GS-01, FD-12). The order is high >
review > none, and mismatch > not_checkable > match.
Example: a fully checked grant_settlement result (illustrative)
This shows the shape once the checks are enabled. Values are invented.
- Item 1 has a payment mismatch, and its invoice PDF shows signs of editing.
- Item 2 is consistent, but its invoice was already used in another filing.
{
"applicant_id": "filing-0042",
"case_type": "grant_settlement",
"verdict": {
"verdict": "REJECT",
"reason_codes": ["FD-13"],
"override_rules_fired": [],
"verdict_explanation": "Invoice reused from another filing."
},
"risk_indicator": "high",
"consistency_result": "mismatch",
"items": [
{
"item_id": "1",
"consistency_result": "mismatch",
"risk_indicator": "high",
"finding_refs": [0, 1],
"missing": [],
"documents": {
"invoice": ["invoice-1.pdf"],
"payment_proof": ["payment-1.pdf"],
"service_description": ["service-1.pdf"]
}
},
{
"item_id": "2",
"consistency_result": "match",
"risk_indicator": "high",
"finding_refs": [2],
"missing": [],
"documents": {
"invoice": ["invoice-2.pdf"],
"payment_proof": ["payment-2.pdf"],
"service_description": ["service-2.pdf"]
}
}
],
"findings": [
{
"check_id": "payment_amount_out_of_tolerance",
"check_category": "grant_consistency",
"severity": "MEDIUM",
"summary": "The amount paid differs from the invoice amount by more than 2 %.",
"evidence_quote": "invoice 4,800.00 EUR, paid 4,500.00 EUR (-6.25 %)",
"source_document_id": "payment-1.pdf",
"source_regions": {"page": 1, "bbox": [72, 410, 520, 436]},
"code": "UP-06a",
"item_id": "1",
"references": null
},
{
"check_id": "pdf_incremental_update_after_creation",
"check_category": "metadata",
"severity": "HIGH",
"summary": "The file metadata indicates later editing.",
"evidence_quote": "created 2026-02-03, modified 2026-05-19 by a different producer",
"source_document_id": "invoice-1.pdf",
"source_regions": {},
"code": "FD-01",
"item_id": "1",
"references": null
},
{
"check_id": "document_reused_other_filing",
"check_category": "grant_cross_case",
"severity": "CRITICAL",
"summary": "The document was already used in another grant filing.",
"evidence_quote": "identical file fingerprint",
"source_document_id": "invoice-2.pdf",
"source_regions": {},
"code": "FD-13",
"item_id": "2",
"references": [
{"applicant_id": "filing-0017", "item_id": "3", "document": "rechnung-3.pdf"}
]
}
]
}(Abridged. message, advisory_score, checker_version and the other existing fields are left
out. The check_id values are examples only; match on code.)
For this case type, read risk_indicator and consistency_result. verdict stays populated for
compatibility (high maps to REJECT, review to ESCALATE, CONDITIONAL or PENDING, none
to PASS), but the outcome is a pointer for review, not a decision.
6. Full examples
Stateful lifecycle
# 1. Create the case with its type and master data
curl -X POST "$ALETHEIA_BASE_URL/v1/applicants" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"applicant_id": "filing-0042",
"case_type": "grant_settlement",
"master_data": {
"applicant": {"name": "Example Trading GmbH", "uid": "ATU12345678"},
"funding_period": {"from": "2025-11-04", "to": "2027-03-31"}
}
}'
# 201 {"applicant_id": "filing-0042", "tenant_id": "...", "created_at": "...", "case_type": "grant_settlement"}
# 2. Upload the documents (any order, any number of calls)
curl -X POST "$ALETHEIA_BASE_URL/v1/applicants/filing-0042/documents" \
-H "Authorization: Bearer $TOKEN" \
-F "files=@application.pdf" -F "files=@invoice-1.pdf" \
-F "files=@payment-1a.pdf" -F "files=@payment-1b.pdf" -F "files=@service-1.pdf"
# 3. Set (or replace) the manifest
curl -X PUT "$ALETHEIA_BASE_URL/v1/applicants/filing-0042/manifest" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"application": ["application.pdf"],
"items": [{"id": "1", "invoice": ["invoice-1.pdf"],
"payment_proof": ["payment-1a.pdf", "payment-1b.pdf"],
"service_description": ["service-1.pdf"]}]}'
# 200 {"applicant_id": "filing-0042", "case_type": "grant_settlement", "manifest": {...}}
# 4. Analyze
curl -X POST "$ALETHEIA_BASE_URL/v1/applicants/filing-0042/analyze" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" -d '{}'In Mode B (shared service token) add -H "X-Tenant-ID: $TENANT" to every call; in Mode A the
tenant comes from the key and the header is ignored, see Agents.
One-shot POST /analyze
curl -X POST "$ALETHEIA_BASE_URL/analyze" -H "Authorization: Bearer $TOKEN" \
-F "applicant_id=filing-0042" \
-F "case_type=grant_settlement" \
-F 'manifest={"application": ["application.pdf"], "items": [{"id": "1", "invoice": ["invoice-1.pdf"], "payment_proof": ["payment-1a.pdf"], "service_description": ["service-1.pdf"]}]}' \
-F 'master_data={"application_date": "2025-11-04"}' \
-F "files=@application.pdf" -F "files=@invoice-1.pdf" \
-F "files=@payment-1a.pdf" -F "files=@service-1.pdf"ZIP
curl -X POST "$ALETHEIA_BASE_URL/analyze/zip" -H "Authorization: Bearer $TOKEN" \
-F "applicant_id=filing-0042" -F "case_type=grant_settlement" \
-F "file=@filing.zip"
# 202 {"job_id": "...", "status": "analyzing", "status_url": "/analyze/zip/<job_id>"}
curl "$ALETHEIA_BASE_URL/analyze/zip/<job_id>" -H "Authorization: Bearer $TOKEN"7. Errors
Case-type errors use the usual error body; detail.error_code names the case.
| Status | error_code | When |
|---|---|---|
422 | unknown_case_type | case_type is not a known case type. |
403 | case_type_not_allowed | The case type exists, but your tenant is not enabled for it. Also on PUT .../manifest and POST .../analyze for an existing case if the tenant's access to its type was withdrawn. |
422 | manifest_requires_case_type | A manifest was sent without a typed case_type (or PUT .../manifest on an account_application case). |
422 | invalid_manifest | Malformed JSON, unknown key, a duplicate filename or item id, a path instead of a filename, or a role the case type does not have. |
422 | duplicate_filename | Two uploaded documents have the same name (or, with a manifest, the same filename in different ZIP folders). |
422 | none | ZIP: two entries with the same path after normalisation, or a symbolic-link entry. |
422 | master_data_not_supported | master_data sent for a case type that takes none (for example account_application). |
422 | invalid_master_data | Malformed JSON, an unknown key, or a field of the wrong type (for example an invalid date). |
404 | none | PUT .../manifest for an applicant that does not exist. |
Example:
{
"detail": {
"detail": "Tenant 'example' is not entitled to case_type 'grant_settlement'.",
"error_code": "case_type_not_allowed"
}
}Pending verification: the Aletheia team's guide shows case-type errors with
detailas an object (detail,error_code), and a403for a tenant not enabled for a case type. The specification'sProblemDetailshasdetailas a string and declares no403or404onPUT /v1/applicants/{id}/manifest. The Aletheia team is confirming the live shape.
On the JSON body of POST /v1/applicants, structural manifest and master-data errors (unknown
key, duplicate filename, invalid date) come back as the standard 422 validation error list.
Not errors: a manifest file that was never uploaded (the item is not_checkable with a
missing entry), an uploaded file the manifest does not name (an unassigned_document finding),
and missing master-data fields (the dependent check is not_checkable).
8. What comes next
This release ships the case-type contract: the fields, the manifest, the ZIP convention, the response shape and the finding codes. Later releases add, without breaking this contract:
- the
grant_settlementchecks, which fillrisk_indicator,consistency_result, per-item results andfindings[].codewith the codes listed above; - automatic role detection inside ZIP folders;
- checks across filings, which use
findings[].references.