{
  "openapi": "3.1.0",
  "info": {
    "title": "PintLint API",
    "version": "0.1.0",
    "description": "Validate and fix UAE e-invoices against PINT AE 1.0.4. Pre-flight only: a pass is not ASP or FTA acceptance. A Thorncliff product."
  },
  "servers": [
    {
      "url": "https://api.pintlint.com"
    },
    {
      "url": "https://api.thorncliff.ai"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/v1/validate": {
      "post": {
        "summary": "Validate a UBL XML or JSON invoice",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Invoice"
              }
            },
            "application/xml": {
              "schema": {
                "type": "string",
                "description": "UBL 2.1 Invoice or CreditNote, PINT AE"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidateResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or bad key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Over 1 MB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Not UBL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fix": {
      "post": {
        "summary": "Fix a JSON invoice",
        "parameters": [
          {
            "name": "apply_suggestions",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Also apply changes that normally need review."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Invoice"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Fix result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FixResult"
                }
              }
            }
          },
          "401": {
            "description": "Missing or bad key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "UBL not supported yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/check": {
      "post": {
        "summary": "Free check (no key)",
        "description": "Powers the validator on pintlint.com. Validates, and for JSON also fixes. 20 checks per IP per day, 500 KB max. Use a key for anything automated.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Invoice"
              }
            },
            "application/xml": {
              "schema": {
                "type": "string",
                "description": "UBL 2.1 Invoice or CreditNote, PINT AE"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Validate result, plus `fix` for JSON and `checks_left_today`"
          },
          "429": {
            "description": "Daily or burst limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/rules": {
      "get": {
        "summary": "List rules",
        "security": [],
        "responses": {
          "200": {
            "description": "Rules"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    },
    "schemas": {
      "Invoice": {
        "type": "object",
        "properties": {
          "invoice_number": {
            "type": "string"
          },
          "issue_date": {
            "type": "string",
            "format": "date"
          },
          "due_date": {
            "type": "string",
            "format": "date"
          },
          "currency": {
            "type": "string",
            "example": "AED"
          },
          "transaction_type_code": {
            "type": "string",
            "example": "00000000"
          },
          "seller": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "trn": {
                "type": "string"
              },
              "address": {
                "type": "object",
                "properties": {
                  "street": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "country_subentity": {
                    "type": "string",
                    "example": "DXB"
                  },
                  "country": {
                    "type": "string",
                    "example": "AE"
                  }
                }
              }
            }
          },
          "customer": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "vat_number": {
                "type": "string"
              },
              "legal_registration": {
                "type": "string"
              },
              "address": {
                "type": "object",
                "properties": {
                  "street": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "country_subentity": {
                    "type": "string",
                    "example": "DXB"
                  },
                  "country": {
                    "type": "string",
                    "example": "AE"
                  }
                }
              }
            }
          },
          "line_items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "description": {
                  "type": "string"
                },
                "quantity": {
                  "type": "number"
                },
                "unit_code": {
                  "type": "string"
                },
                "unit_price": {
                  "type": "number"
                },
                "tax_category": {
                  "enum": [
                    "S",
                    "Z",
                    "E",
                    "O"
                  ]
                },
                "tax_percent": {
                  "type": "number"
                },
                "tax_amount": {
                  "type": "number"
                }
              }
            }
          },
          "totals": {
            "type": "object",
            "properties": {
              "tax_exclusive": {
                "type": "number"
              },
              "tax": {
                "type": "number"
              },
              "payable": {
                "type": "number"
              }
            }
          }
        }
      },
      "Finding": {
        "type": "object",
        "properties": {
          "rule": {
            "type": "string",
            "example": "IBR-132-AE"
          },
          "severity": {
            "enum": [
              "error",
              "warning"
            ]
          },
          "source": {
            "enum": [
              "official",
              "ported",
              "thorncliff"
            ]
          },
          "path": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "fix": {
            "type": "string"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "ValidateResult": {
        "type": "object",
        "properties": {
          "valid": {
            "type": "boolean"
          },
          "format": {
            "enum": [
              "json",
              "ubl"
            ]
          },
          "document_type": {
            "enum": [
              "Invoice",
              "CreditNote"
            ]
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Finding"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Finding"
            }
          },
          "spec": {
            "type": "string"
          },
          "disclaimer": {
            "type": "string"
          }
        }
      },
      "FixResult": {
        "type": "object",
        "properties": {
          "corrected": {
            "$ref": "#/components/schemas/Invoice"
          },
          "changes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "old": {},
                "new": {},
                "reason": {
                  "type": "string"
                },
                "applied": {
                  "type": "boolean"
                }
              }
            }
          },
          "needs_review": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "old": {},
                "proposed": {},
                "alternatives": {
                  "type": "array"
                },
                "reason": {
                  "type": "string"
                },
                "applied": {
                  "type": "boolean"
                }
              }
            }
          },
          "needs_input": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "question": {
                  "type": "string"
                }
              }
            }
          },
          "valid_after_fix": {
            "type": "boolean"
          },
          "remaining_errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Finding"
            }
          }
        }
      }
    }
  }
}