{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/astranexo-com/json-schema/astranexo-com-electronic-document-request-schema.json",
  "title": "ElectronicDocumentRequest",
  "x-generated": "2026-11-01",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/aster-openapi.yaml#/components/schemas/ElectronicDocumentRequest",
  "type": "object",
  "required": [
    "document",
    "commercial_info",
    "issuer",
    "items"
  ],
  "properties": {
    "document": {
      "$ref": "#/$defs/DocumentBlock"
    },
    "commercial_info": {
      "$ref": "#/$defs/CommercialInfo"
    },
    "issuer": {
      "$ref": "#/$defs/Party"
    },
    "receiver": {
      "$ref": "#/$defs/Receiver"
    },
    "items": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/Item"
      }
    },
    "totals": {
      "$ref": "#/$defs/Totals"
    },
    "reference": {
      "$ref": "#/$defs/Reference"
    },
    "other_charges": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/OtherCharge"
      }
    },
    "environment": {
      "$ref": "#/$defs/Environment"
    },
    "callback_url": {
      "type": "string",
      "format": "uri",
      "description": "URL adicional que recibe los webhooks de este documento (firmados con el secreto del primer webhook activo, si existe)."
    },
    "api_config": {
      "$ref": "#/$defs/ApiConfig"
    },
    "delivery": {
      "$ref": "#/$defs/Delivery"
    }
  },
  "$defs": {
    "Address": {
      "type": "object",
      "description": "Ubicación según los catálogos de Hacienda (alias del bloque `location`).",
      "properties": {
        "province": {
          "type": "string"
        },
        "canton": {
          "type": "string"
        },
        "district": {
          "type": "string"
        },
        "neighborhood": {
          "type": "string"
        },
        "details": {
          "type": "string",
          "description": "Otras señas."
        },
        "other_signs": {
          "type": "string",
          "description": "Alias de `details`."
        }
      }
    },
    "ApiConfig": {
      "type": "object",
      "properties": {
        "simulate": {
          "type": "string",
          "enum": [
            "accepted",
            "rejected"
          ],
          "description": "Pide un veredicto simulado (solo claves de prueba; `422 simulation_not_available` con claves de producción)."
        },
        "language": {
          "type": "string",
          "enum": [
            "es",
            "en"
          ],
          "description": "Idioma de los mensajes de validación."
        },
        "callback_url": {
          "type": "string",
          "format": "uri",
          "description": "Igual que `callback_url` en la raíz."
        },
        "environment": {
          "$ref": "#/$defs/Environment"
        }
      }
    },
    "CommercialCode": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string"
        },
        "code": {
          "type": "string"
        }
      }
    },
    "CommercialInfo": {
      "type": "object",
      "required": [
        "currency",
        "sale_condition",
        "payment_method"
      ],
      "properties": {
        "currency": {
          "type": "string",
          "description": "Moneda ISO 4217."
        },
        "exchange_rate": {
          "type": [
            "number",
            "string"
          ],
          "description": "Tipo de cambio; obligatorio si la moneda no es `CRC`."
        },
        "sale_condition": {
          "type": "string",
          "description": "Condición de venta (Nota 5, `01`–`15`, `99`) o nombre (`cash`, `credit`, `consignment`…)."
        },
        "sale_condition_other": {
          "type": "string",
          "description": "Obligatorio con `sale_condition` `99`."
        },
        "payment_method": {
          "type": "string",
          "description": "Medio de pago (Nota 6, `01`–`07`, `99`) o nombre (`cash`, `card`, `check`, `transfer`, `sinpe`, `digital`, `other`)."
        },
        "payment_method_other": {
          "type": "string",
          "description": "Obligatorio con `payment_method` `99`."
        },
        "credit_terms": {
          "type": [
            "string",
            "number"
          ],
          "description": "Plazo del crédito (alias `credit_days`)."
        }
      }
    },
    "Delivery": {
      "type": "object",
      "properties": {
        "email": {
          "type": "boolean",
          "description": "Envía el documento por correo cuando Hacienda lo acepte."
        },
        "recipients": {
          "type": "array",
          "maxItems": 5,
          "description": "Destinatarios; por defecto, el correo del receptor.",
          "items": {
            "type": "string",
            "format": "email"
          }
        }
      }
    },
    "Discount": {
      "type": "object",
      "required": [
        "amount"
      ],
      "properties": {
        "amount": {
          "type": "number"
        },
        "code": {
          "type": "string",
          "description": "Código de descuento."
        },
        "other_code": {
          "type": "string",
          "description": "Alias `other_discount_code`."
        },
        "reason": {
          "type": "string",
          "description": "Naturaleza del descuento (alias `nature`)."
        }
      }
    },
    "DocumentBlock": {
      "type": "object",
      "required": [
        "document_type",
        "date",
        "situation"
      ],
      "properties": {
        "document_type": {
          "type": "string",
          "enum": [
            "01",
            "02",
            "03",
            "04",
            "08",
            "09",
            "10"
          ],
          "description": "`01` factura, `02` nota de débito, `03` nota de crédito, `04` tiquete, `08` factura de compra, `09` factura de exportación, `10` recibo electrónico de pago."
        },
        "activity_code": {
          "type": "string",
          "description": "Código de actividad económica del emisor (por ejemplo `620100` o `9511.0`). Obligatorio salvo en facturas de compra."
        },
        "provider_system_id": {
          "type": "string",
          "description": "Identificación del proveedor de sistemas. Opcional con claves de organización (por defecto, AstraNexo)."
        },
        "date": {
          "type": "string",
          "format": "date-time",
          "description": "Fecha de emisión (ISO 8601 con zona horaria). No puede ser futura."
        },
        "situation": {
          "type": "string",
          "enum": [
            "1",
            "2",
            "3"
          ],
          "description": "`1` normal, `2` contingencia, `3` sin internet."
        },
        "branch": {
          "type": "string",
          "description": "Sucursal (alias `sucursal`). Por defecto `001`."
        },
        "terminal": {
          "type": "string",
          "description": "Terminal (alias `punto_venta`). Por defecto `00001`."
        },
        "clave": {
          "type": "string",
          "pattern": "^[0-9A-Z]{50}$",
          "description": "Clave numérica propia (alias `key`). Debe enviarse con `consecutive_number`."
        },
        "consecutive_number": {
          "type": "string",
          "pattern": "^\\d{20}$",
          "description": "Consecutivo propio de 20 dígitos (alias `consecutive`)."
        }
      }
    },
    "Environment": {
      "type": "string",
      "enum": [
        "staging",
        "production"
      ],
      "description": "Ambiente de Hacienda. Con claves de Aster lo decide la clave."
    },
    "Exoneration": {
      "type": "object",
      "required": [
        "document_type",
        "document_number",
        "institution",
        "emission_date"
      ],
      "properties": {
        "document_type": {
          "type": "string",
          "description": "Tipo de documento de exoneración (alias `type`)."
        },
        "type_other": {
          "type": "string"
        },
        "document_number": {
          "type": "string"
        },
        "institution": {
          "type": "string",
          "description": "Código de la institución que emite la exoneración."
        },
        "institution_name": {
          "type": "string"
        },
        "emission_date": {
          "type": "string",
          "format": "date-time"
        },
        "percentage": {
          "type": "number",
          "description": "Puntos porcentuales exonerados (alias `exonerated_rate`)."
        },
        "amount": {
          "type": "number",
          "description": "Monto exonerado (alias `exonerated_amount`)."
        },
        "article": {
          "type": [
            "string",
            "integer"
          ]
        },
        "inciso": {
          "type": [
            "string",
            "integer"
          ]
        }
      }
    },
    "Item": {
      "type": "object",
      "required": [
        "cabys_code",
        "quantity",
        "unit",
        "description"
      ],
      "properties": {
        "line_number": {
          "type": "integer",
          "description": "Número de línea (se asigna si se omite)."
        },
        "cabys_code": {
          "type": "string",
          "description": "Código CABYS de 13 dígitos. Debe existir."
        },
        "tariff_code": {
          "type": "string",
          "description": "Partida arancelaria (facturas de exportación)."
        },
        "quantity": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "unit": {
          "type": "string",
          "description": "Unidad de medida. Las de servicio (`Sp`, `Os`, `Spe`, `St`, `Al`…) requieren un CABYS de servicio (5–9) y las de bienes uno de bienes (0–4)."
        },
        "description": {
          "type": "string",
          "maxLength": 200
        },
        "price": {
          "type": "number",
          "minimum": 0,
          "description": "Precio unitario."
        },
        "unit_price": {
          "type": "number",
          "minimum": 0,
          "description": "Alias de `price`."
        },
        "discount": {
          "type": "array",
          "description": "Descuentos.",
          "items": {
            "$ref": "#/$defs/Discount"
          }
        },
        "discounts": {
          "type": "array",
          "description": "Alias de `discount`.",
          "items": {
            "$ref": "#/$defs/Discount"
          }
        },
        "tax": {
          "description": "Impuestos de la línea; acepta un objeto o un arreglo.",
          "oneOf": [
            {
              "type": "array",
              "items": {
                "$ref": "#/$defs/Tax"
              }
            },
            {
              "$ref": "#/$defs/Tax"
            }
          ]
        },
        "exoneration": {
          "$ref": "#/$defs/Exoneration"
        },
        "is_service": {
          "type": "boolean",
          "description": "Solo se usa si el CABYS falta o no es numérico."
        },
        "commercial_codes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/CommercialCode"
          }
        },
        "surtido_items": {
          "type": "array",
          "description": "Componentes de un surtido o combo.",
          "items": {
            "$ref": "#/$defs/SurtidoItem"
          }
        },
        "subtotal": {
          "type": "number",
          "description": "Se calcula si se omite."
        },
        "net_tax": {
          "type": "number",
          "description": "Se recalcula a partir de los impuestos."
        },
        "total": {
          "type": "number",
          "description": "Se recalcula a partir de los impuestos."
        },
        "export_amount": {
          "type": "number"
        },
        "transaction_type": {
          "type": "string",
          "description": "Tipo de transacción (FE 4.4)."
        },
        "medication_registry": {
          "type": "string",
          "description": "Registro de medicamentos."
        },
        "pharmaceutical_form": {
          "type": "string",
          "description": "Forma farmacéutica."
        }
      }
    },
    "OtherCharge": {
      "type": "object",
      "required": [
        "document_type",
        "amount"
      ],
      "properties": {
        "document_type": {
          "type": "string",
          "description": "Tipo de otro cargo (Nota 16), por ejemplo `06` impuesto de servicio 10 %."
        },
        "id_number": {
          "type": "string",
          "description": "Identificación del tercero."
        },
        "name": {
          "type": "string",
          "description": "Nombre del tercero."
        },
        "detail": {
          "type": "string"
        },
        "percentage": {
          "type": "number"
        },
        "amount": {
          "type": "number"
        }
      }
    },
    "Party": {
      "type": "object",
      "description": "Emisor o receptor.",
      "required": [
        "type",
        "id",
        "name"
      ],
      "properties": {
        "type": {
          "type": "string",
          "description": "Tipo de identificación: `01` física, `02` jurídica, `03` DIMEX, `04` NITE, `05` extranjero no domiciliado, `06` no contribuyente; o nombre (`fisica`, `juridica`, `dimex`, `nite`, `extranjero`)."
        },
        "id": {
          "type": "string",
          "description": "Número de identificación."
        },
        "name": {
          "type": "string"
        },
        "commercial_name": {
          "type": "string"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "phone": {
          "$ref": "#/$defs/Phone"
        },
        "address": {
          "$ref": "#/$defs/Address"
        },
        "location": {
          "$ref": "#/$defs/Address"
        },
        "foreign_address": {
          "type": "string",
          "description": "Dirección en el extranjero (facturas de exportación)."
        }
      }
    },
    "Phone": {
      "description": "Teléfono como texto (`\"22223333\"`, código de país 506) u objeto.",
      "oneOf": [
        {
          "type": "string"
        },
        {
          "type": "object",
          "properties": {
            "country_code": {
              "type": "string"
            },
            "number": {
              "type": "string"
            }
          }
        }
      ]
    },
    "Receiver": {
      "description": "Receptor. Obligatorio salvo en tiquetes.",
      "allOf": [
        {
          "$ref": "#/$defs/Party"
        },
        {
          "type": "object",
          "properties": {
            "activity_code": {
              "type": "string",
              "description": "Actividad económica del receptor."
            }
          }
        }
      ]
    },
    "Reference": {
      "type": "object",
      "description": "Documento de referencia (notas de crédito y débito, sustituciones, recibos de pago).",
      "required": [
        "document_type",
        "date"
      ],
      "properties": {
        "document_type": {
          "type": "string",
          "description": "Tipo de documento referido (Nota 10, `01`–`20`, `99`; alias `type`)."
        },
        "number": {
          "type": "string",
          "description": "Clave (50 caracteres) o número del documento referido."
        },
        "date": {
          "type": "string",
          "description": "Fecha del documento referido."
        },
        "code": {
          "type": "string",
          "description": "Motivo (Nota 9, `01`–`17`, `99`)."
        },
        "reason": {
          "type": "string",
          "description": "Explicación."
        },
        "type_other": {
          "type": "string",
          "description": "Obligatorio con `document_type` `99`."
        },
        "code_other_description": {
          "type": "string",
          "description": "Obligatorio con `code` `99`."
        }
      }
    },
    "SurtidoItem": {
      "type": "object",
      "properties": {
        "cabys_code": {
          "type": "string"
        },
        "quantity": {
          "type": "number"
        },
        "unit": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "price": {
          "type": "number"
        },
        "subtotal": {
          "type": "number"
        },
        "total": {
          "type": "number"
        },
        "tax": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              },
              "rate_type": {
                "type": "string"
              },
              "rate": {
                "type": "number"
              },
              "amount": {
                "type": "number"
              }
            }
          }
        },
        "discount": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "amount": {
                "type": "number"
              },
              "code": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "Tax": {
      "type": "object",
      "required": [
        "type"
      ],
      "properties": {
        "type": {
          "type": "string",
          "description": "Código de impuesto: `01` IVA, `02` selectivo de consumo, … `99` otros."
        },
        "rate_code": {
          "type": "string",
          "description": "Código de tarifa IVA (alias `rate_type`): `01` 0 %, `02` 1 %, `03` 2 %, `04` 4 %, `05` transitorio 0 %, `06` transitorio 4 %, `07` transitorio 8 %, `08` general 13 %, `09` reducida 0,5 %, `10` exenta, `11` 0 % sin derecho a crédito.",
          "enum": [
            "01",
            "02",
            "03",
            "04",
            "05",
            "06",
            "07",
            "08",
            "09",
            "10",
            "11"
          ]
        },
        "rate": {
          "type": "number",
          "description": "Tarifa en porcentaje."
        },
        "amount": {
          "type": "number",
          "description": "Monto del impuesto; se calcula si se omite."
        },
        "taxable_base": {
          "type": "number",
          "description": "Base imponible especial."
        },
        "assumed_tax_amount": {
          "type": "number",
          "description": "Impuesto asumido por el emisor."
        },
        "exoneration_amount": {
          "type": "number",
          "description": "Monto exonerado; se calcula a partir de la exoneración de la línea."
        }
      }
    },
    "Totals": {
      "type": "object",
      "description": "Resumen del comprobante. El servidor lo recalcula a partir de las líneas; solo `total_other_charges` y `total_iva_returned` se toman de la solicitud. Acepta también los alias `sales`, `discounts`, `net_sales`, `taxes`, `other_charges` y un bloque `breakdown`.",
      "properties": {
        "total_taxed_services": {
          "type": "number"
        },
        "total_exempt_services": {
          "type": "number"
        },
        "total_exonerated_services": {
          "type": "number"
        },
        "total_no_sujeto_services": {
          "type": "number"
        },
        "total_taxed_goods": {
          "type": "number"
        },
        "total_exempt_goods": {
          "type": "number"
        },
        "total_exonerated_goods": {
          "type": "number"
        },
        "total_no_sujeta_goods": {
          "type": "number"
        },
        "total_sales": {
          "type": "number"
        },
        "total_discount": {
          "type": "number"
        },
        "total_net_sales": {
          "type": "number"
        },
        "total_taxes": {
          "type": "number"
        },
        "total_assumed_tax": {
          "type": "number"
        },
        "total_iva_returned": {
          "type": "number",
          "description": "IVA devuelto (servicios de salud pagados con tarjeta)."
        },
        "total_other_charges": {
          "type": "number"
        },
        "total": {
          "type": "number"
        }
      }
    }
  }
}