Constaia
Concepts

Advanced privacy

Pixelated copy of the document with redact, masked fields with mask_fields, deletion and export by metadata (rights to erasure and access) and result retention per template or account.

Besides deciding what happens to the original file (see Storage & privacy), Constaia gives you tools to minimise the data you keep and to handle people's rights:

ToolWhat for
redactKeep a copy of the document with identifiers, signature and photo pixelated.
mask_fieldsStore only part of a value (12****78Z) while validation uses the full value.
Deletion by metadataDelete every analysis of a person in one call.
Export by metadataHand a person all their data.
RetentionDelete results automatically after a period.

Everything can be set per request or in a template, and mask_fields and retention also as account defaults in the dashboard (Settings → Privacy).

Pixelated copy (redact)

With redact: true (or export: ["redacted_image"], which is equivalent) the analysis generates a JPEG copy of the document with these areas pixelated:

  • the document number and the other identifiers read (tax IDs, IBAN, support numbers…), using their boxes;
  • the MRZ band, located by the local reader;
  • the handwritten signature and the holder's photo, using the boxes the model detects. If the photo isn't located on an identity document, a safety area is pixelated (the left side of the front; on passports, the bottom band with the MRZ).

For PDFs, the first rendered page is pixelated.

curl https://api.constaia.com/v1/analyze \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  -F "file=@dni.jpg" \
  -F 'options={"expect":"es_dni","storage":"none","redact":true}'

The copy arrives as a signed URL in exports.redacted_image (it expires after 24 h; retrieve the analysis again for a new one). It is kept even if the original is deleted (for example with storage: "none") for the template's result retention or, if it sets none, 30 days. That way you can show the document to a reviewer or archive it without keeping the original.

Masked fields (mask_fields)

{ "expect": "es_dni", "mask_fields": ["document_number", "mrz"] }

The fields in mask_fields (up to 50) are stored masked: the first two and last three characters stay visible (12345678Z → 12****78Z; values of 5 characters or fewer become all asterisks). Objects and lists are masked inside, and nested paths are accepted (employee.tax_id).

  • Validation uses the full value: the ID check letter or the minimum age are checked before masking.
  • The synchronous response of POST /v1/analyze carries the full value, once. Everything stored comes out masked: GET /v1/analyses/{id}, lists, webhooks, link callbacks, exports and the dashboard.
  • The value is also masked inside checks[].message and verdict.reasons[].message.
  • The MRZ repeats the document number: add mrz if you want it masked too.
  • With progressive results (stream=true), the local event carries no mrz, barcode or identifiers when there are mask_fields.
  • In a dossier, a masked value can't be used to compare holders: if you mask the document number, the same_holder check relies on the name and date of birth.

If an analysis has no mask_fields (neither in the request nor in the template), the account's are used.

Deletion by metadata (right to erasure)

Store the person's identifier in your system in metadata ({ "user_id": "123" }) and you can delete all their analyses at once:

curl -X DELETE -G https://api.constaia.com/v1/analyses \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  --data-urlencode "metadata[user_id]=123"
Response
{ "object": "deletion", "deleted": 3, "ids": ["an_01J9Z8Q3K4M5N6P7Q8R9S0T1V2", "an_…", "an_…"] }
  • You need at least one metadata[key]=value filter; several filters must all match. Without a filter: 422 metadata_filter_required.
  • It deletes, in the key's mode, the file, the results, the exports (the pixelated copy too) and the metadata of each analysis, just like DELETE /v1/analyses/{id}.
  • It also empties the body of the webhook deliveries that carried those results.
  • At most 10,000 analyses per request: if deleted is 10,000, call it again.
  • It is recorded in the account's audit log.

Export by metadata (right of access)

curl -G https://api.constaia.com/v1/analyses/export \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  --data-urlencode "metadata[user_id]=123" \
  --data-urlencode "format=json"
ParameterDescription
metadata[key]At least one. They must all match.
formatjson (default): { "object": "list", "data": [...], "has_more": false, "url": "/v1/analyses/export" } with the full analysis object. csv or xlsx: a file download.

Returns up to 1,000 analyses of the key's mode, newest first; has_more: true if there are more. Fields in mask_fields come out masked, as stored.

Result retention

storage decides how long the file lives; retention decides how long the results live (extracted data, verdict, checks, file name and exports):

  1. The template's retention_days (1–3650 days), if the analysis used one.
  2. Otherwise, the account's period ("Result retention" under Settings → Privacy).
  3. If there's none, results are kept until you delete them (except with keep_results: false, which doesn't store them).

The period starts when the analysis finishes. A daily job deletes expired ones. A minimal record of the analysis (type, verdict, credits and metadata) is kept for usage, billing and analytics: that's why metadata should carry internal identifiers, not personal data.

Webhook bodies with results

Webhook and link callback deliveries that carry results are emptied (they become { type, purged: true, purged_at }, keeping their status, attempts and response code) 7 days after being delivered successfully, and as soon as the results of any of those analyses are deleted (retention, single deletion or deletion by metadata). A pending delivery whose body is emptied becomes failed: an empty body is never resent.

Next steps

On this page