AltScore
Borrower Central (BC)

Data Models API

This API allows managing data models in the system. It provides endpoints to create, read, update, and delete data models, as well as to perform queries with filtering and pagination options.

The DataModel Object

The DataModel object represents a data model in the system.

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "path": "/ruta/ejemplo",
  "key": "modelo_ejemplo",
  "label": "Modelo de Ejemplo",
  "entityType": "identity",
  "priority": 1,
  "order": null,
  "allowedValues": null,
  "createdAt": "2023-05-01T12:00:00Z",
  "updatedAt": "2023-05-02T14:30:00Z",
  "isSensitive": false,
  "metadata": {
    "descripcion": "Este es un modelo de ejemplo"
  },
  "processing": null
}

Attributes

AttributeDescriptionTypeRequired
idUnique identifier of the data modelStringYes
pathPath of the data modelStringYes
keyUnique key of the data modelStringYes
labelDescriptive label of the modelStringYes
entityTypeEntity type of the modelStringYes
priorityPriority of the modelIntegerNo
orderOrder of the modelIntegerNo
allowedValuesAllowed values for the fieldArrayNo
createdAtCreation date and timeStringYes
updatedAtLast update date and timeStringNo
isSensitiveMarks an identity DataModel as sensitive (PII)BooleanNo
metadataAdditional metadata of the modelObjectNo
processingProcessing definition of a document data model; null or absent when none is defined. See Document ProcessingObjectNo

Valid Entity Types

The entityType field must be one of the following values:

Entity TypeDescription
identityIdentity records (national ID, passport, etc.)
contactContact information fields
documentDocument type definitions
borrowerBorrower entity configuration
borrower_fieldCustom fields for borrowers
point_of_contactPoint of contact fields
authorizationAuthorization type definitions
stepWorkflow step definitions
metricMetric definitions
signalSignal definitions written by the conversational Goal node
goalGoal definitions counted by Conversation Insights (label is the name, metadata.description the description, order optional; a PATCH with "order": null clears it). The key cannot be changed after creation
deal_fieldCustom fields for deals
deal_stepDeal workflow step definitions
deal_roleDeal role definitions
decisionDecision type definitions
accounting_documentAccounting document type definitions
asset_fieldCustom fields for assets
asset_groupAsset group definitions for categorizing assets

Available Operations

Create a New Data Model

Creates a new data model in the system.

POST /v1/data-models

Input Parameters:

ParameterDescriptionTypeRequired
pathPath of the data modelStringYes
keyUnique key of the modelStringYes
labelDescriptive label of the modelStringYes
entityTypeEntity type of the modelStringYes
priorityPriority of the modelIntegerNo*
orderOrder of the modelIntegerNo
allowedValuesAllowed values for the modelArrayNo
metadataAdditional metadata of the modelObjectNo
isSensitiveMarks an identity DataModel as sensitive (PII)BooleanNo

*For entityType: "identity", priority is required and must be greater than or equal to -1.

Request Example:

{
  "path": "/ruta/ejemplo",
  "key": "modelo_ejemplo",
  "label": "Modelo de Ejemplo",
  "entityType": "identity",
  "priority": 1,
  "isSensitive": false,
  "metadata": {
    "descripcion": "Este es un modelo de ejemplo"
  }
}

Successful Response:

{
  "id": "123e4567-e89b-12d3-a456-426614174000"
}

Update a Data Model

Updates an existing data model.

PATCH /v1/data-models/:data_model_id

Path Parameters:

ParameterDescription
:data_model_idID of the data model to update

Input Parameters:

ParameterDescriptionTypeRequired
pathNew path of the data modelStringNo
keyNew key of the modelStringNo
labelNew label of the modelStringNo
orderNew order of the modelIntegerNo
priorityNew priority of the modelIntegerNo
allowedValuesAllowed values for the modelArrayNo
metadataNew metadata of the modelObjectNo

Note: isSensitive cannot be updated via PATCH. Use the dedicated make-sensitive endpoint below.

Request Example:

{
  "label": "Updated Example Model",
  "priority": 2
}

Successful Response:

The response will be the updated DataModel object.

Make an Identity Data Model Sensitive

Marks an existing identity DataModel as sensitive and encrypts existing identities for that key.

PUT /v1/data-models/:data_model_id/make-sensitive

Path Parameters:

ParameterDescription
:data_model_idID of the data model to update

Successful Response:

The response will be the updated DataModel object (with isSensitive: true).

Save the Processing Definition of a Document Data Model

Saves the processing block of a document data model: the fields to extract, the validation conditions with what is expected of each one, and, for advanced configurations, several document types, validations, logic rules and document rules. In the Hub these are the Details tab (fields to extract) and the Validation tab of the data model. The Document Processing guide explains each part, maps every Hub name to its key and describes the rule grammar. This is the only way to write processing; POST and PATCH never touch it.

PUT /v1/data-models/:data_model_id/processing

Requires the configurations.write permission. Only data models with entityType: "document" accept it.

Path Parameters:

ParameterDescription
:data_model_idID of the document data model

Input Parameters:

ParameterDescriptionTypeRequired
documentTypesThe document types, 1 to 20. A configuration made in the Hub has one. With several, order matters: when a file looks like two types, the first one winsArrayYes
documentRulesacceptedTypes (anyOf or allOf over type keys) and document-level validationsObjectNo
enabledfalse stops the document from being processed and keeps existing results. Default trueBooleanNo
expectedVersionThe definitionVersion you edited. If the stored one is different, the save is rejected with 409IntegerNo

Each item of documentTypes:

ParameterDescriptionTypeRequired
keyLowercase letters, digits and _, starting with a letter, up to 64 charactersStringYes
labelName shown in the Hub, up to 120 charactersStringYes
descriptionWhat the document is, up to 1000 characters. Files are recognized by it. Required with two or more types. With a single type it can be absent, null or blank (stored as null): then there is no recognition step and every file is read directly as that typeStringWith 2+ types
minConfidenceMinimum type confidence, 0 to 1. Default 0.6NumberNo
fields1 to 40 fieldsArrayYes
validationsUp to 50 validations: key, label, severity (blocking or warning), rulesArrayNo
logicUp to 50 logic rules: key, label, rulesArrayNo

Each item of fields is a row of the Details tab, of the Validation tab, or of both:

ParameterDescriptionTypeRequired
keySame pattern as the type key, unique within the typeStringYes
labelName shown in the Hub, up to 120 characters. The Hub shows the key when absentStringNo
typestring, number, integer, date, boolean or listStringYes
descriptionWhat to extract or to check, up to 500 characters. It is sent to the model; for a boolean row it is the questionStringYes
purposeextraction (a field to extract), validation (a condition) or both (a field to extract that is also a condition). When absent, the row is a field to extract, as before this key existedStringNo
expectedWhat a condition expects; see below. Required when purpose is validation or both, and not allowed otherwise. It is never sent to the modelObjectDepends
requiredAdvanced options only. Whether the file is not valid without this value. Default false. Not allowed as true on a row with purpose: use {"op": "exists"} insteadBooleanNo
minConfidenceMinimum confidence, 0 to 1. Default 0.7, 0.5 for booleanNumberNo
formatnumberFormat (auto, latam, us) on number and integer fields, dateOrder (auto, dmy, mdy, ymd) on date fieldsObjectNo

expected is {"op": ..., "value": ...}. Which op each row type accepts:

opvalueRow typesMeaning
existsnoneallA value was read
equalsa value of the row's type (dates as YYYY-MM-DD, text up to 500 characters)string, number, integer, dateText ignores case and accents, not punctuation; numbers compare numerically; dates by day
equals{"ref": "borrower.label"}stringThe customer's name, by similarity from 0.85
equals{"ref": "identity.<key>"}string, number, integer, dateOne of the customer's identities, compared like equals. Sensitive identities are rejected
is_true, is_falsenonebooleanExpected Yes / No
greater_than, greater_than_or_equal, less_than, less_than_or_equala number (whole on integer rows)number, integerExact comparison
after, beforea date, YYYY-MM-DDdateStrictly after or before
one_of1 to 200 non-empty stringsstringEqual to any of them, compared like equals

A condition's key does not need to be among the fields to extract. Keys are unique within a type, so a value that is extracted and checked is one row with purpose: "both".

Request Example:

Two fields to extract and two conditions, on a single type without a description:

{
  "expectedVersion": 1,
  "documentTypes": [
    {
      "key": "acta_constitucion",
      "label": "Acta de constitución",
      "fields": [
        { "key": "razon_social", "type": "string", "description": "Razón social de la compañía" },
        { "key": "fecha_constitucion", "type": "date", "description": "Fecha de constitución" },
        { "key": "es_acta", "type": "boolean", "description": "¿El documento es un acta de constitución de una compañía?",
          "purpose": "validation", "expected": { "op": "is_true" } },
        { "key": "puede_endeudar", "type": "boolean", "description": "¿El acta autoriza al representante a endeudar a la empresa?",
          "purpose": "validation", "expected": { "op": "is_true" } }
      ]
    }
  ]
}

An advanced configuration, with a described type, required fields, a validation and a logic rule:

{
  "expectedVersion": 2,
  "documentTypes": [
    {
      "key": "planilla_luz",
      "label": "Planilla de luz",
      "description": "Planilla mensual del servicio de energía eléctrica con el titular, la dirección del suministro, la fecha de emisión y el total a pagar.",
      "fields": [
        { "key": "titular", "label": "Titular", "type": "string", "description": "Nombre completo del titular de la cuenta", "required": true },
        { "key": "fecha_emision", "label": "Fecha de emisión", "type": "date", "description": "Fecha de emisión de la planilla", "required": true, "minConfidence": 0.85, "format": { "dateOrder": "dmy" } },
        { "key": "monto_total", "label": "Total a pagar", "type": "number", "description": "Total a pagar del periodo", "required": true, "format": { "numberFormat": "us" } }
      ],
      "validations": [
        { "key": "vigente", "label": "Emitida en los últimos 60 días", "severity": "blocking", "rules": { "field": "fecha_emision", "operator": "within_last_days", "value": 60 } }
      ],
      "logic": [
        { "key": "aplica_beneficio", "label": "Total menor a 50", "rules": { "field": "monto_total", "operator": "less_than", "value": 50 } }
      ]
    }
  ],
  "documentRules": { "acceptedTypes": { "anyOf": ["planilla_luz"] } }
}

Successful Response:

The updated DataModel object. Its processing holds the definition with the defaults filled in. A field to extract is stored without purpose, so it is the same object as a field saved before this key existed.

The server also derives two things from the conditions, which you see when you read the data model back:

  • each row with purpose validation or both becomes a blocking validation of its type, with the key __expected_<field key>, added after your own validations;
  • with at least one condition, documentRules.unrecognizedFiles is invalid: a file that matches none of the types is invalid instead of needs_review. It only applies when there is a recognition step.

Both are managed by the server. They are dropped from any body you send and derived again, so a GET followed by a PUT of the same processing stores the same definition, and a hand-edited __expected_* validation is replaced by the one its row produces. A user key can never start with _, so these never collide with yours.

Four more fields are managed by the server (they are ignored if you send them):

FieldDescription
definitionVersionStarts at 1 and goes up only when the types or rules change. Toggling enabled or saving the same definition keeps it
definitionHashFingerprint of the types, rows and rules. Results store it, so you can tell when they are older than the definition. A definition saved before purpose and expected existed keeps its hash
updatedAtWhen the definition last changed
updatedByWho changed it

Validation errors:

Every problem is reported at once, in a single 400 with errorSubCode: "PROCESSING_DEFINITION_INVALID". Each entry of details.errors has a code, a path (a JSON pointer into the body you sent) and a message:

{
  "code": "BadRequestError",
  "message": "The processing definition has 2 problems",
  "details": {
    "errorSubCode": "PROCESSING_DEFINITION_INVALID",
    "errors": [
      { "code": "PROCESSING_UNKNOWN_FIELD", "path": "/documentTypes/0/validations/0/rules/field", "message": "Field 'fecha' is not defined in type 'planilla_luz'" },
      { "code": "PROCESSING_OPERATOR_TYPE_MISMATCH", "path": "/documentTypes/0/logic/0/rules/operator", "message": "Operator 'greater_than' does not apply to a 'string' field" }
    ]
  }
}
codeWhen
PROCESSING_SCHEMA_INVALIDWrong JSON type, missing required property, unknown property, or text too long. Also a purpose that is not one of the three values, required: true on a row with purpose, or a type without description when there are two or more types
PROCESSING_INVALID_KEYA key does not match the allowed pattern
PROCESSING_DUPLICATE_KEYA repeated type key, field key within a type, validation or logic key within a type, or document validation key. A validation and a logic rule of the same type cannot share a key either
PROCESSING_LIMIT_EXCEEDEDOver a limit: 20 types, 40 fields, 50 validations, 50 logic rules, 50 rules per tree, 200 in_list or one_of values, or more than five levels of nesting. A type's validations plus its conditions count together against the 50 (path /documentTypes/i/fields)
PROCESSING_UNKNOWN_TYPEacceptedTypes, an operand or a field: reference names a type that is not defined
PROCESSING_UNKNOWN_FIELDA rule or a field: reference names a field that is not defined
PROCESSING_UNKNOWN_OPERATORThe operator does not exist (is_pending and the authentication operators are not available)
PROCESSING_OPERATOR_TYPE_MISMATCHThe operator does not apply to the field's type
PROCESSING_INVALID_VALUEvalue is missing or present against what the operator expects, has the wrong type, is a date that is not YYYY-MM-DD, is a negative day count, or threshold is outside 0 to 1 or used with an operator other than similar_to
PROCESSING_INVALID_REFA malformed reference. In expected, also a reference other than borrower.label or identity.<key>, or borrower.label on a row that is not string
PROCESSING_REF_UNKNOWN_IDENTITYidentity.<key> names an identity data model that does not exist
PROCESSING_REF_SENSITIVE_IDENTITYidentity.<key> names a sensitive identity, which is never decrypted for a comparison
PROCESSING_INVALID_MIN_CONFIDENCEA minConfidence outside 0 to 1
PROCESSING_INVALID_FORMATA format key that does not apply to the field's type, or an unknown value
PROCESSING_INVALID_RULEA rule node that is not exactly one of all, any, not or a rule; an empty group; or a document validation operand without its type
PROCESSING_INVALID_EXPECTEDexpected is missing on a condition, present on a field to extract, not an object, has an unknown op or one that does not apply to the row's type, or its value is missing, extra, of the wrong type, an empty string, a date that is not YYYY-MM-DD, a fraction on an integer row, or an empty list. path points at .../fields/j/expected, its op or its value

Other errors of this endpoint:

StatuserrorSubCodeWhen
404The data model does not exist
409PROCESSING_DEFINITION_VERSION_CONFLICTexpectedVersion does not match. details.currentVersion has the stored one; reload before saving again
422DATA_MODEL_PROCESSING_NOT_DOCUMENTThe data model is not a document data model

Test a Processing Definition

Runs a definition against one uploaded file and returns the result. Nothing is stored: no document, no results and no images. It is what Test with a file does in the Hub.

POST /v1/data-models/:data_model_key/processing/test

Requires the configurations.write permission. Unlike the PUT, this route takes the data model key, not its id; it is the same key as the documents it applies to.

Path Parameters:

ParameterDescription
:data_model_keyKey of the document data model

Form Parameters (multipart/form-data):

ParameterDescriptionTypeRequired
fileThe file to test, up to 20 MBFileYes
definitionA definition as JSON text, with the same body as the PUT above. When absent, the stored definition is usedStringNo
borrowerIdA customer whose name and identities are used for borrower.label and identity.* referencesStringNo
contextJSON text {"borrower": {"label": "..."}, "identities": {"<key>": "..."}}, used when borrowerId is absentStringNo

Successful Response:

{
  "persisted": false,
  "definitionHash": "sha256:5d1c...",
  "modelId": "model-id",
  "now": "2026-10-21T15:00:00Z",
  "attempts": 1,
  "modelCalls": 2,
  "file": {
    "outcome": "processed",
    "documentType": { "key": "planilla_luz", "label": "Planilla de luz", "confidence": 1.0, "minConfidence": 0.6 },
    "fields": [ "..." ],
    "validations": [ "..." ],
    "logic": [ "..." ],
    "status": "valid",
    "statusReasons": [],
    "pages": [ { "page": 2, "width": 1240, "height": 1600, "mimeType": "image/jpeg", "imageBase64": "..." } ],
    "pageCount": 2,
    "crops": []
  },
  "pagesTruncated": false,
  "pageCount": 2,
  "document": { "status": "valid", "statusReasons": [], "acceptedTypes": { "...": "..." }, "validations": [] },
  "mode": "both",
  "extraction": {
    "current": true,
    "status": "extracted",
    "values": { "valor_pagar": 42.75, "fecha_emision": "2026-10-15", "valor_mayor_50": false },
    "evidence": { "...": "..." }
  },
  "validation": {
    "current": true,
    "status": "valid",
    "valid": true,
    "reasons": [],
    "rows": [ "..." ],
    "otherRules": []
  }
}

file has the same shape as one attachment's result in the Documents API (section "Get the Processing Results of a Document"), except that page images come inline as base64 and there are no crops. At most 10 page images come back: first the pages where a value was found (values to review before the rest), then the lowest-numbered pages, all in page order. pageCount, in file and at the top, is the number of pages in the file, and pagesTruncated is true when there were more than 10 page images.

mode, extraction and validation are the same as for one attachment in the Documents API, computed with the tested definition: mode is extraction, validation or both, and a block is null when the definition has no part of that kind. current is always true, and pageUrl and cropUrl in the blocks are null, because the pages come inline. With a single file, a document that needs several types will usually not be satisfied.

Errors:

StatuserrorSubCodeWhen
400PROCESSING_TEST_FILE_EMPTYThe file is empty
400PROCESSING_TEST_FILE_TOO_LARGEThe file is over 20 MB
400PROCESSING_TEST_CONTEXT_CONFLICTBoth borrowerId and context were sent
400PROCESSING_DEFINITION_INVALIDThe definition sent is not valid (same details.errors as the PUT)
404No document data model with that key
422DOCUMENT_PROCESSING_NOT_CONFIGUREDNo definition was sent and the data model has none stored
503DOCUMENT_PROCESSING_*The processing service could not complete the run. See "Processing errors" in the Documents API

Get a Data Model

Retrieves the information of a specific data model.

GET /v1/data-models/:data_model_id

Path Parameters:

ParameterDescription
:data_model_idID of the data model to retrieve

Successful Response:

The response will be a complete DataModel object.

Delete a Data Model

Deletes a data model from the system.

DELETE /v1/data-models/:data_model_id

Path Parameters:

ParameterDescription
:data_model_idID of the data model to delete

Successful Response:

Status code 204 (No Content) if the deletion was successful.

List Data Models

Retrieves a paginated list of data models with filtering and sorting options.

GET /v1/data-models

Query Parameters:

ParameterDescriptionType
searchText to search in data modelsString
pagePage number (default: 1)Integer
per-pageItems per page (default: 10)Integer
entity-typeFilter by entity typeString
sort-byField to sort byString
sort-directionSorting direction (asc or desc)String

Successful Response:

The response will be a paginated list of DataModel objects.

Error Handling

The API may return the following error codes:

CodeDescription
400Bad Request
401Unauthorized
403Forbidden
404Not Found
409Conflict (processing definition version)
422Unprocessable Entity (processing)
500Internal Server Error
503Service Unavailable (processing test)

Errors will include a descriptive message in the response body.