{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://sirf2.org/schemas/sirf.schema.json",
  "title": "Standard Industry Reporting Format — Line Schema",
  "description": "Validates a single line in a SIRF JSON Lines file. Each line must be either a Header record (line 1) or an Account record (lines 2+), distinguished by the recordType discriminator field.",
  "oneOf": [
    { "$ref": "#/$defs/header" },
    { "$ref": "#/$defs/accountRecord" }
  ],
  "examples": [
    {
      "recordType": "Header",
      "sirfVersion": "2.0",
      "reportingStartDate": "2025-02-01",
      "reportingEndDate": "2025-02-28",
      "portfolioId": "farringdon-mortgages",
      "recordCount": 342
    },
    {
      "recordType": "Account",
      "person": {
        "customerId": "FAR-C10482",
        "title": "Mrs",
        "firstName": "Patricia",
        "lastName": "Okafor",
        "dob": "1968-07-30"
      },
      "address": {
        "buildingName": "Rose Cottage",
        "buildingNumber": "8",
        "line1": "Church Lane",
        "line2": "Clifton",
        "city": "Bristol",
        "postalCode": "BS8 4CD"
      },
      "account": {
        "accountId": "POK-7714",
        "accountType": "Mortgage",
        "accountSubtype": "Residential",
        "status": "UpToDate",
        "startDate": "2018-03-01",
        "repayment": 499,
        "repaymentPeriod": 300,
        "currentBalance": 87450,
        "paymentFrequency": "Monthly"
      }
    },
    {
      "recordType": "Account",
      "person": {
        "customerId": "FAR-C20931",
        "title": "Mr",
        "firstName": "James",
        "lastName": "Thornton",
        "dob": "1979-11-14",
        "email": "j.thornton@example.com",
        "phone": "447700900142"
      },
      "address": {
        "buildingNumber": "42",
        "line1": "Maple Street",
        "city": "Manchester",
        "postalCode": "M1 4BT"
      },
      "account": {
        "accountId": "JTH-2293",
        "accountType": "CreditCard",
        "status": "UpToDate",
        "startDate": "2021-09-15",
        "repayment": 75,
        "repaymentPeriod": 60,
        "currentBalance": 1240,
        "paymentFrequency": "Monthly",
        "creditLimit": 5000,
        "minimumPayment": 25,
        "cashAdvances": 200,
        "cashAdvancesCount": 2
      }
    },
    {
      "recordType": "Account",
      "person": {
        "customerId": "FAR-C31057",
        "title": "Ms",
        "firstName": "Sarah",
        "middleName": "Louise",
        "lastName": "Mitchell",
        "dob": "1985-03-22"
      },
      "address": {
        "buildingNumber": "14",
        "line1": "Birchwood Avenue",
        "line2": "Headingley",
        "city": "Leeds",
        "postalCode": "LS6 2AB"
      },
      "account": {
        "accountId": "SML-4821",
        "accountType": "UnsecuredLoan",
        "status": "Delinquent2",
        "startDate": "2023-06-01",
        "daysPastDue": 62,
        "repayment": 185,
        "repaymentPeriod": 36,
        "currentBalance": 3421,
        "paymentFrequency": "Monthly",
        "flags": [
          {
            "type": "Arrangement",
            "startDate": "2024-11-01"
          },
          {
            "type": "Queried",
            "startDate": "2024-09-02",
            "endDate": "2024-10-15"
          }
        ]
      }
    }
  ],
  "$defs": {
    "header": {
      "title": "Standard Industry Reporting Format — File Header",
      "description": "The first record in a SIRF JSON Lines file. Carries reporting period and portfolio metadata that applies to all subsequent account records in the file. Processors should read this record first, then apply its context to all following lines.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "recordType",
        "sirfVersion",
        "reportingStartDate",
        "reportingEndDate",
        "portfolioId",
        "recordCount"
      ],
      "properties": {
        "recordType": {
          "title": "Record Type",
          "description": "Discriminator field identifying this as a file header record.",
          "type": "string",
          "const": "Header",
          "examples": ["Header"]
        },
        "sirfVersion": {
          "title": "SIRF Version",
          "description": "Version of the Standard Industry Reporting Format this file conforms to.",
          "type": "string",
          "const": "2.0",
          "examples": ["2.0"]
        },
        "reportingStartDate": {
          "title": "Reporting Start Date",
          "description": "Start of the reporting period (inclusive), in YYYY-MM-DD format.",
          "type": "string",
          "format": "date",
          "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$",
          "examples": ["2025-02-01"]
        },
        "reportingEndDate": {
          "title": "Reporting End Date",
          "description": "End of the reporting period (inclusive), in YYYY-MM-DD format.",
          "type": "string",
          "format": "date",
          "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$",
          "examples": ["2025-02-28"]
        },
        "portfolioId": {
          "title": "Portfolio ID",
          "description": "Identifier for the lender portfolio. Lowercase kebab-case, prefixed with the reporting institution's slug to avoid collisions across independently-operated systems. Unique within the context of the reporting institution. Examples: 'farringdon-mortgages', 'farringdon-unsecured'.",
          "type": "string",
          "pattern": "^[a-z0-9-]+$",
          "examples": ["farringdon-mortgages", "farringdon-unsecured", "farringdon-credit-cards"]
        },
        "recordCount": {
          "title": "Record Count",
          "description": "Total number of account records in this file, excluding the header.",
          "type": "integer",
          "minimum": 1,
          "examples": [342]
        }
      }
    },
    "accountRecord": {
      "title": "Standard Industry Reporting Format — Account Record",
      "description": "A single consumer credit account record in a SIRF JSON Lines file. Must be preceded by a Header record which carries the reporting period and portfolio context for all records in the file. Groups the individual (person), their address, and the account data (account).",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "recordType",
        "person",
        "address",
        "account"
      ],
      "properties": {
        "recordType": {
          "title": "Record Type",
          "description": "Discriminator field identifying this as an account data record.",
          "type": "string",
          "const": "Account",
          "examples": ["Account"]
        },
        "person": {
          "$ref": "#/$defs/person"
        },
        "address": {
          "$ref": "#/$defs/address"
        },
        "account": {
          "$ref": "#/$defs/account"
        }
      }
    },
    "account": {
      "title": "Account",
      "description": "The credit account being reported: identifiers, product type, status, balances, repayment terms, and flags.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "accountId",
        "accountType",
        "status"
      ],
      "if": {
        "properties": {
          "accountType": { "enum": ["CreditCard", "ChargeCard", "Budget"] }
        },
        "required": ["accountType"]
      },
      "then": {
        "required": ["creditLimit"],
        "if": {
          "properties": {
            "accountType": { "const": "CreditCard" }
          },
          "required": ["accountType"]
        },
        "then": {
          "required": ["minimumPayment"]
        }
      },
      "else": {
        "properties": {
          "creditLimit": false,
          "cashAdvances": false,
          "cashAdvancesCount": false,
          "minimumPayment": false
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "status": { "enum": ["Delinquent1", "Delinquent2", "Delinquent3", "Delinquent4", "Delinquent5", "Delinquent6"] }
            },
            "required": ["status"]
          },
          "then": {
            "required": ["daysPastDue"]
          }
        }
      ],
      "properties": {
        "accountId": {
          "title": "Account ID",
          "description": "Unique identifier for the credit account within the lender's system. Alphanumeric characters and hyphens only.",
          "type": "string",
          "pattern": "^[A-Za-z0-9-]+$",
          "examples": ["SML-4821", "JTH-0093", "POK7714"]
        },
        "portfolioId": {
          "title": "Portfolio ID",
          "description": "Identifier for the lender portfolio the account belongs to. Used only when the account record is sent on its own by HTTP POST. Omit in JSON Lines files, where the portfolioId in the Header record applies to every account. Same format as the Header portfolioId: lowercase kebab-case, prefixed with the reporting institution's slug.",
          "type": "string",
          "pattern": "^[a-z0-9-]+$",
          "examples": ["farringdon-mortgages", "farringdon-unsecured", "farringdon-credit-cards"]
        },
        "accountIdChange": {
          "title": "Account ID Change",
          "description": "Updated account identifier, provided when the accountId for this account has changed. Processors should replace the previous accountId with this value. Same format as accountId.",
          "type": "string",
          "pattern": "^[A-Za-z0-9-]+$",
          "examples": ["SML-4822", "JTH-0094"]
        },
        "accountType": {
          "title": "Account Type",
          "description": "The category of credit product. Determines which fields are applicable and how balances and payments are interpreted.",
          "type": "string",
          "enum": [
            "HirePurchase",
            "UnsecuredLoan",
            "Mortgage",
            "Budget",
            "CreditCard",
            "ChargeCard",
            "CurrentAccount",
            "BasicBankAccount"
          ],
          "examples": ["UnsecuredLoan", "Mortgage", "CreditCard"]
        },
        "status": {
          "title": "Account Status",
          "description": "Monthly payment performance indicator.",
          "type": "string",
          "enum": [
            "Unclassified",
            "Dormant",
            "UpToDate",
            "Delinquent1",
            "Delinquent2",
            "Delinquent3",
            "Delinquent4",
            "Delinquent5",
            "Delinquent6",
            "Defaulted"
          ],
          "examples": ["UpToDate", "Delinquent2", "Defaulted"]
        },
        "startDate": {
          "title": "Start Date",
          "description": "The date the account was opened. In YYYY-MM-DD format.",
          "type": "string",
          "format": "date",
          "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$",
          "examples": ["2023-06-01", "2018-03-15"]
        },
        "closeDate": {
          "title": "Close Date",
          "description": "The date the account was closed. In YYYY-MM-DD format. Omit if the account is still open.",
          "type": "string",
          "format": "date",
          "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$",
          "examples": ["2025-01-31", "2024-06-15"]
        },
        "daysPastDue": {
          "title": "Days Past Due",
          "description": "Number of days the account is past due. Required when status is Delinquent1 through Delinquent6.",
          "type": "integer",
          "minimum": 0,
          "examples": [35, 62, 90]
        },
        "repayment": {
          "title": "Repayment Amount",
          "description": "Scheduled repayment amount per period in GBP. Whole pounds, rounded to the nearest pound.",
          "type": "integer",
          "minimum": 0,
          "examples": [185, 499, 76]
        },
        "repaymentPeriod": {
          "title": "Repayment Period",
          "description": "Total number of repayment periods at origination — not the number of periods remaining. Reflects the full agreement term.",
          "type": "integer",
          "minimum": 1,
          "examples": [36, 300, 24]
        },
        "startBalance": {
          "title": "Start Balance",
          "description": "Total balance in GBP at the time the account was opened. Whole pounds, rounded to the nearest pound.",
          "type": "integer",
          "minimum": 0,
          "examples": [6660, 15000, 250000]
        },
        "currentBalance": {
          "title": "Current Balance",
          "description": "Total outstanding balance in GBP at the point of reporting. Whole pounds, rounded to the nearest pound. May be negative.",
          "type": "integer",
          "examples": [3421, 87450, 0, -120]
        },
        "paymentFrequency": {
          "title": "Payment Frequency",
          "description": "How often scheduled repayments are made.",
          "type": "string",
          "enum": [
            "Monthly",
            "Weekly",
            "Fortnightly",
            "Quarterly",
            "Annually",
            "Irregular"
          ],
          "examples": ["Monthly", "Weekly"]
        },
        "accountSubtype": {
          "title": "Account Subtype",
          "description": "Further classification of the account within its type.",
          "type": "string",
          "enum": [
            "Residential",
            "BuyToLet",
            "Flexible"
          ],
          "examples": ["Residential", "BuyToLet", "Flexible"]
        },
        "creditLimit": {
          "title": "Credit Limit",
          "description": "Maximum credit available on the account in GBP. Required when accountType is 'CreditCard', 'ChargeCard', or 'Budget'; omit for all other account types. Whole pounds, rounded to the nearest pound.",
          "type": "integer",
          "minimum": 0,
          "examples": [5000, 2500, 10000]
        },
        "cashAdvances": {
          "title": "Cash Advances",
          "description": "Total value of cash advances taken on the account in GBP. Applies to CreditCard, ChargeCard, and Budget accounts only. Whole pounds, rounded to the nearest pound.",
          "type": "integer",
          "minimum": 0,
          "examples": [250, 0, 500]
        },
        "cashAdvancesCount": {
          "title": "Cash Advances Count",
          "description": "Number of cash advance transactions on the account. Applies to CreditCard, ChargeCard, and Budget accounts only.",
          "type": "integer",
          "minimum": 0,
          "examples": [1, 0, 3]
        },
        "minimumPayment": {
          "title": "Minimum Payment",
          "description": "Minimum payment due in GBP. Required on CreditCard accounts. Whole pounds, rounded to the nearest pound.",
          "type": "integer",
          "minimum": 0,
          "examples": [25, 36, 100]
        },
        "flags": {
          "title": "Flags",
          "description": "Optional markers indicating special conditions on the account. Multiple flags may be applied simultaneously, but each flag type may appear at most once per account. Omit the field entirely if no flags apply.",
          "type": "array",
          "items": { "$ref": "#/$defs/flag" },
          "uniqueItems": true,
          "examples": [
            [{ "type": "Arrangement", "startDate": "2024-11-01" }],
            [{ "type": "Partial", "startDate": "2024-11-30" }],
            [{ "type": "Arrangement", "startDate": "2024-11-01" }, { "type": "Queried", "startDate": "2024-09-02", "endDate": "2024-10-15" }]
          ]
        }
      }
    },
    "flag": {
      "title": "Flag",
      "description": "A marker indicating a special condition on the account, with the optional period during which it applies.",
      "type": "object",
      "additionalProperties": false,
      "required": ["type"],
      "examples": [
        { "type": "Arrangement", "startDate": "2024-11-01" },
        { "type": "Queried", "startDate": "2024-09-02", "endDate": "2024-10-15" }
      ],
      "properties": {
        "type": {
          "title": "Flag Type",
          "description": "The special condition that applies to the account.",
          "type": "string",
          "enum": [
            "Deceased",
            "Partial",
            "DebtAssigned",
            "DebtSold",
            "GoneAway",
            "Recourse",
            "VoluntaryTermination",
            "Arrangement",
            "DebtManagement",
            "PaidThirdParty",
            "Queried",
            "TransientAssociation"
          ],
          "examples": ["Arrangement", "Queried", "Partial"]
        },
        "startDate": {
          "title": "Flag Start Date",
          "description": "Date the flag started to apply (inclusive), in YYYY-MM-DD format. Optional.",
          "type": "string",
          "format": "date",
          "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$",
          "examples": ["2024-11-01", "2024-09-02"]
        },
        "endDate": {
          "title": "Flag End Date",
          "description": "Date the flag stopped applying (inclusive), in YYYY-MM-DD format. Optional. Omit while the flag still applies. When startDate is also present, endDate must be after startDate.",
          "type": "string",
          "format": "date",
          "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$",
          "examples": ["2024-10-15"]
        }
      }
    },
    "person": {
      "title": "Person",
      "description": "The individual associated with the credit account. First name, last name, and date of birth are mandatory.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "firstName",
        "lastName",
        "dob"
      ],
      "examples": [
        {
          "customerId": "FAR-C31057",
          "title": "Ms",
          "firstName": "Sarah",
          "lastName": "Mitchell",
          "dob": "1985-03-22"
        }
      ],
      "properties": {
        "customerId": {
          "title": "Customer ID",
          "description": "The lender's own identifier for the customer, the same across all of that customer's accounts with the lender. Optional. Alphanumeric characters and hyphens only.",
          "type": "string",
          "pattern": "^[A-Za-z0-9-]+$",
          "examples": ["FAR-C31057", "FAR-C10482"]
        },
        "title": {
          "title": "Title",
          "description": "Honorific title. Optional.",
          "type": "string",
          "enum": ["Mr", "Mrs", "Ms", "Miss", "Mx", "Dr"],
          "examples": ["Mr", "Ms", "Dr"]
        },
        "firstName": {
          "title": "First Name",
          "description": "Given name. Mandatory. Minimum 2 characters.",
          "type": "string",
          "minLength": 2,
          "examples": ["Sarah", "James", "Patricia"]
        },
        "middleName": {
          "title": "Middle Name",
          "description": "Middle name or names. Optional.",
          "type": "string",
          "examples": ["Louise", "John"]
        },
        "lastName": {
          "title": "Last Name",
          "description": "Family name / surname. Mandatory. Minimum 2 characters.",
          "type": "string",
          "minLength": 2,
          "examples": ["Mitchell", "Thornton", "Okafor"]
        },
        "suffix": {
          "title": "Suffix",
          "description": "Name suffix, e.g. 'Junior', 'Senior', 'III'. Optional.",
          "type": "string",
          "examples": ["Junior", "Senior", "III"]
        },
        "dob": {
          "title": "Date of Birth",
          "description": "Date of birth in YYYY-MM-DD format. Mandatory.",
          "type": "string",
          "format": "date",
          "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$",
          "examples": ["1985-03-22", "1972-11-08"]
        },
        "email": {
          "title": "Email Address",
          "description": "Email address of the account holder. Optional.",
          "type": "string",
          "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$",
          "examples": ["sarah.mitchell@example.com", "j.thornton@example.co.uk"]
        },
        "phone": {
          "title": "Phone Number",
          "description": "Phone number in E.164 format with UK country code, digits only, e.g. '447911123456'. Optional.",
          "type": "string",
          "pattern": "^44\\d{10}$",
          "examples": ["447911123456", "441612345678"]
        }
      }
    },
    "address": {
      "title": "Address",
      "description": "UK residential address. line1 and postalCode are required.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "line1",
        "postalCode"
      ],
      "examples": [
        {
          "buildingNumber": "14",
          "line1": "Birchwood Avenue",
          "line2": "Headingley",
          "city": "Leeds",
          "postalCode": "LS6 2AB"
        },
        {
          "subBuilding": "Flat 2",
          "buildingNumber": "37",
          "line1": "Victoria Road",
          "city": "Manchester",
          "postalCode": "M14 5EF"
        }
      ],
      "properties": {
        "subBuilding": {
          "title": "Sub-Building",
          "description": "Sub-unit within a building, e.g. 'Flat 3', 'Unit B'. Optional.",
          "type": "string",
          "examples": ["Flat 3", "Unit B", "Ground Floor"]
        },
        "buildingName": {
          "title": "Building Name",
          "description": "Named building, e.g. 'Rose Cottage', 'Acacia House'. Optional.",
          "type": "string",
          "examples": ["Rose Cottage", "Acacia House"]
        },
        "buildingNumber": {
          "title": "Building Number",
          "description": "Street number as a string to accommodate values like '5A'. Optional.",
          "type": "string",
          "examples": ["14", "37", "5A"]
        },
        "line1": {
          "title": "Line 1",
          "description": "Primary street address line, e.g. 'Main Street'. Required.",
          "type": "string",
          "examples": ["Birchwood Avenue", "Victoria Road", "Main Street"]
        },
        "line2": {
          "title": "Line 2",
          "description": "Secondary address line, e.g. a locality or district. Optional.",
          "type": "string",
          "examples": ["Headingley", "Clifton", "Beeston"]
        },
        "city": {
          "title": "City",
          "description": "Town or city, e.g. 'Nottingham'. Optional.",
          "type": "string",
          "examples": ["Leeds", "Manchester", "Nottingham"]
        },
        "postalCode": {
          "title": "Postal Code",
          "description": "UK postcode including the internal space, e.g. 'NG8 1JD'. Required.",
          "type": "string",
          "pattern": "^[A-Z]{1,2}\\d[A-Z\\d]?\\s\\d[A-Z]{2}$",
          "examples": ["LS6 2AB", "M14 5EF", "NG8 1JD"]
        },
        "deliveryPoint": {
          "title": "Delivery Point",
          "description": "Royal Mail Unique Delivery Point Reference Number. 8-digit numeric string. Optional.",
          "type": "string",
          "pattern": "^\\d{8}$",
          "examples": ["27483910", "12345678"]
        }
      }
    }
  }
}
