{
    "$id": "https://se.kivra.com/schemas/json/retail/ps/v1.0",
    "$schema": "http://json-schema.org/draft-07/schema#",
    "description": "Prescription specification issued by pharmacies and connected to a receipt in Kivra. The format is based on discussions with pharmacies and data from the Swedish eHealth Agency. Version 1.0 — first release 2025-03-11.",
    "type": "object",
    "properties": {
        "business_unit": {
            "description": "Merchant information (the pharmacy issuing the specification).",
            "type": "object",
            "properties": {
                "name": {
                    "type": "string"
                },
                "service_id": {
                    "description": "Id created when then business is registered in kivra",
                    "type": "string",
                    "minLength": 42,
                    "maxLength": 42,
                    "pattern": "^[0-9]{10}[0-9a-fA-F]{32}$"
                },
                "unit_id": {
                    "type": "string",
                    "description": "Internal merchant shop/business unit id"
                },
                "organization_number": {
                    "type": "string",
                    "description": "Swedish organisationsnummer or vat reg number"
                },
                "contact": {
                    "type": "object",
                    "description": "Merchant contact information name, address, phone etc",
                    "properties": {
                        "address": {
                            "title": "address",
                            "description": "An address following the convention of http://microformats.org/wiki/hcard",
                            "type": "object",
                            "properties": {
                                "street_address": {
                                    "type": "string"
                                },
                                "extended_address": {
                                    "type": "string"
                                },
                                "post_box": {
                                    "type": "string"
                                },
                                "locality": {
                                    "type": "string"
                                },
                                "postal_code": {
                                    "type": "string"
                                },
                                "region": {
                                    "type": "string"
                                },
                                "country_name": {
                                    "type": "string"
                                },
                                "type": {
                                    "type": "object",
                                    "title": "address type",
                                    "description": "is address (physical/email) related to business, home, etc",
                                    "properties": {
                                        "type": {
                                            "enum": [
                                                "home",
                                                "business"
                                            ]
                                        }
                                    }
                                }
                            },
                            "anyOf": [
                                {
                                    "required": [
                                        "street_address"
                                    ]
                                },
                                {
                                    "required": [
                                        "post_box"
                                    ]
                                }
                            ],
                            "required": [
                                "locality",
                                "postal_code"
                            ]
                        },
                        "email": {
                            "type": "string",
                            "format": "email"
                        },
                        "phone": {
                            "title": "generic phone number",
                            "description": "generic format for phone numbers where strict format can not be enforced, use only for phone number to be displayed",
                            "type": "string",
                            "pattern": "^(\\(?((\\+|(00))[0-9]{1,3})\\)?)?( ?-?\\(?[0-9]+\\)?)+$"
                        },
                        "website": {
                            "type": "string",
                            "format": "uri"
                        }
                    }
                },
                "geo_location": {
                    "type": "object",
                    "title": "Geographic location (long/lat)",
                    "description": "A geographical coordinate",
                    "properties": {
                        "latitude": {
                            "type": "number"
                        },
                        "longitude": {
                            "type": "number"
                        }
                    },
                    "required": [
                        "latitude",
                        "longitude"
                    ]
                }
            },
            "required": [
                "name",
                "service_id",
                "organization_number",
                "contact"
            ]
        },
        "cashier": {
            "description": "Identifies the person handling the purchase if applicable",
            "title": "cashier name and id",
            "type": "object",
            "properties": {
                "id": {
                    "type": "string"
                },
                "name": {
                    "type": "string"
                }
            },
            "additionalProperties": false
        },
        "receipt_identifier": {
            "description": "Receipt identifiers: sequence number and/or extended number with or without barcode representation",
            "title": "receipt identifier",
            "type": "object",
            "properties": {
                "sequence_number": {
                    "type": "integer",
                    "description": "a sequence number as stipulated by the swedish tax authorities, not mandatory for PS."
                },
                "extended_number": {
                    "type": "object",
                    "description": "a more complex receipt number if applicable, must be unique in given context",
                    "properties": {
                        "value": {
                            "type": "string",
                            "description": "data that will be presented as a barcode on the receipt"
                        },
                        "type": {
                            "type": "string",
                            "enum": [
                                "Interleaved2Of5",
                                "EAN13",
                                "EAN8",
                                "Codabar",
                                "Code39",
                                "Code93",
                                "Code128",
                                "AztecCode",
                                "Datamatrix",
                                "PDF417",
                                "QRCode"
                            ],
                            "description": "barcode representation of any data"
                        },
                        "context": {
                            "type": "string",
                            "enum": [
                                "store",
                                "chain",
                                "global"
                            ],
                            "description": "in what context is the value (receipt number) unique, note GLOBAL can only be used if a digital receipt provider receipt id is used"
                        }
                    },
                    "required": [
                        "value",
                        "context"
                    ]
                }
            },
            "required": [
                "extended_number"
            ],
            "additionalProperties": false
        },
        "time_of_purchase": {
            "description": "ISO 8601 date/time format: YYYY-MM-DDThh:mm:ssTZD",
            "type": "string",
            "format": "date-time"
        },
        "currency": {
            "description": "The receipt default currency. This gives the currency for all amounts in the receipt. If applicable overriding currencies can be added to the tender parts",
            "title": "ISO-4217 currency codes",
            "type": "string",
            "pattern": "^[a-zA-Z]{3}$"
        },
        "amount_with_benefit": {
            "description": "Amount with the high-cost benefit applied. Human prescriptions only; usually equals amount_paid_by_benefit but differs when insurances are involved.",
            "type": "number",
            "minimum": 0
        },
        "amount_without_benefit": {
            "description": "Amount without the high-cost benefit. Given on both animal and human prescriptions.",
            "type": "number",
            "minimum": 0
        },
        "amount_paid_by_benefit": {
            "description": "Amount paid by the high-cost benefit. Human prescriptions only; usually equals amount_with_benefit but differs when insurances are involved.",
            "type": "number",
            "minimum": 0
        },
        "amount_to_pay": {
            "description": "Final amount the customer pays. Given on both animal and human prescriptions.",
            "type": "number",
            "minimum": 0
        },
        "totals": {
            "description": "Total amounts and types, for example vat, gross, paid. Included when the prescription contains goods/services the customer pays tax on; the VAT is then added here.",
            "type": "array",
            "items": {
                "oneOf": [
                    {
                        "title": "Paid total amount",
                        "description": "paid: gross amount including discount and rounding.",
                        "type": "object",
                        "allOf": [
                            {
                                "title": "Total amounts presented on the receipt",
                                "description": "One or more totals like net amount, vat, paid, discount",
                                "type": "object",
                                "properties": {
                                    "amount": {
                                        "type": "number",
                                        "minimum": 0
                                    },
                                    "refund": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "true if amount to customer, example: on return of goods"
                                    }
                                },
                                "required": [
                                    "amount"
                                ]
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "enum": [
                                            "paid"
                                        ]
                                    },
                                    "sub_totals": {
                                        "type": "array",
                                        "items": {
                                            "anyOf": [
                                                {
                                                    "title": "Amount received from customer",
                                                    "description": "Use with total/paid if paid gives the total amount paid and the subtotal gives what is given by  customer",
                                                    "type": "object",
                                                    "properties": {
                                                        "type": {
                                                            "type": "string",
                                                            "enum": [
                                                                "received"
                                                            ]
                                                        },
                                                        "amount": {
                                                            "type": "number",
                                                            "minimum": 0
                                                        },
                                                        "text": {
                                                            "description": "optional explaining text",
                                                            "type": "object",
                                                            "properties": {
                                                                "type": {
                                                                    "type": "string",
                                                                    "enum": [
                                                                        "array"
                                                                    ]
                                                                },
                                                                "collection": {
                                                                    "type": "array",
                                                                    "description": "Arbitray array of strings used where additional info needed at some part",
                                                                    "items": {
                                                                        "type": "string"
                                                                    }
                                                                }
                                                            },
                                                            "required": [
                                                                "type",
                                                                "collection"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "type",
                                                        "amount"
                                                    ],
                                                    "additionalProperties": false
                                                },
                                                {
                                                    "title": "Returned sub total",
                                                    "description": "Use with total/paid if paid gives the total amount paid and the subtotal gives what is returned to customer",
                                                    "type": "object",
                                                    "properties": {
                                                        "type": {
                                                            "type": "string",
                                                            "enum": [
                                                                "returned"
                                                            ]
                                                        },
                                                        "amount": {
                                                            "type": "number",
                                                            "minimum": 0
                                                        },
                                                        "text": {
                                                            "description": "optional explaining text",
                                                            "type": "object",
                                                            "properties": {
                                                                "type": {
                                                                    "type": "string",
                                                                    "enum": [
                                                                        "array"
                                                                    ]
                                                                },
                                                                "collection": {
                                                                    "type": "array",
                                                                    "description": "Arbitray array of strings used where additional info needed at some part",
                                                                    "items": {
                                                                        "type": "string"
                                                                    }
                                                                }
                                                            },
                                                            "required": [
                                                                "type",
                                                                "collection"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "type",
                                                        "amount"
                                                    ],
                                                    "additionalProperties": false
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        ],
                        "required": [
                            "type"
                        ]
                    },
                    {
                        "title": "Total gross amount presented on the receipt",
                        "description": "gross: total including vat, excluding discounts",
                        "type": "object",
                        "allOf": [
                            {
                                "title": "Total amounts presented on the receipt",
                                "description": "One or more totals like net amount, vat, paid, discount",
                                "type": "object",
                                "properties": {
                                    "amount": {
                                        "type": "number",
                                        "minimum": 0
                                    },
                                    "refund": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "true if amount to customer, example: on return of goods"
                                    }
                                },
                                "required": [
                                    "amount"
                                ]
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "enum": [
                                            "gross"
                                        ],
                                        "description": "gross: total including vat."
                                    },
                                    "sub_totals": {
                                        "type": "array",
                                        "items": {
                                            "anyOf": [
                                                {
                                                    "title": "Sub totals can be used on all totals if needed",
                                                    "description": "One or more sub totals eligible for bonus",
                                                    "type": "object",
                                                    "allOf": [
                                                        {
                                                            "title": "Common sub total properties",
                                                            "description": "Common properties for all sub totals",
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "minimum": 0
                                                                },
                                                                "refund": {
                                                                    "type": "boolean",
                                                                    "default": false,
                                                                    "description": "true if amount to customer, example: on return of goods"
                                                                },
                                                                "text": {
                                                                    "description": "optional explaining text",
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "type": {
                                                                            "type": "string",
                                                                            "enum": [
                                                                                "array"
                                                                            ]
                                                                        },
                                                                        "collection": {
                                                                            "type": "array",
                                                                            "description": "Arbitray array of strings used where additional info needed at some part",
                                                                            "items": {
                                                                                "type": "string"
                                                                            }
                                                                        }
                                                                    },
                                                                    "required": [
                                                                        "type",
                                                                        "collection"
                                                                    ]
                                                                }
                                                            },
                                                            "required": [
                                                                "amount"
                                                            ]
                                                        },
                                                        {
                                                            "properties": {
                                                                "type": {
                                                                    "type": "string",
                                                                    "enum": [
                                                                        "eligible_for_frequent_shopper_points"
                                                                    ]
                                                                },
                                                                "points": {
                                                                    "type": "integer",
                                                                    "minimum": 0,
                                                                    "description": "loyalty points gained/lost in transaction"
                                                                }
                                                            }
                                                        }
                                                    ]
                                                },
                                                {
                                                    "title": "Sub totals can be used on all totals if needed",
                                                    "description": "One or more sub totals for example one for each tax percentage",
                                                    "type": "object",
                                                    "allOf": [
                                                        {
                                                            "title": "Common sub total properties",
                                                            "description": "Common properties for all sub totals",
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "minimum": 0
                                                                },
                                                                "refund": {
                                                                    "type": "boolean",
                                                                    "default": false,
                                                                    "description": "true if amount to customer, example: on return of goods"
                                                                },
                                                                "text": {
                                                                    "description": "optional explaining text",
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "type": {
                                                                            "type": "string",
                                                                            "enum": [
                                                                                "array"
                                                                            ]
                                                                        },
                                                                        "collection": {
                                                                            "type": "array",
                                                                            "description": "Arbitray array of strings used where additional info needed at some part",
                                                                            "items": {
                                                                                "type": "string"
                                                                            }
                                                                        }
                                                                    },
                                                                    "required": [
                                                                        "type",
                                                                        "collection"
                                                                    ]
                                                                }
                                                            },
                                                            "required": [
                                                                "amount"
                                                            ]
                                                        },
                                                        {
                                                            "properties": {
                                                                "type": {
                                                                    "type": "string",
                                                                    "description": "Can be one of the total amount types or any other description what the subtotal is about"
                                                                }
                                                            }
                                                        }
                                                    ]
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        ],
                        "required": [
                            "type"
                        ]
                    },
                    {
                        "title": "Total tax amount presented on the receipt",
                        "description": "Tax releated total",
                        "type": "object",
                        "properties": {
                            "type": {
                                "type": "string",
                                "enum": [
                                    "vat"
                                ]
                            },
                            "amount": {
                                "type": "number",
                                "minimum": 0
                            },
                            "refund": {
                                "type": "boolean",
                                "default": false,
                                "description": "true if amount to customer, example: on return of goods"
                            },
                            "sub_totals": {
                                "type": "array",
                                "description": "add sub total for each tax percentage used",
                                "items": {
                                    "title": "Sub totals can be used on all totals but is mostly used on VAT",
                                    "description": "One or more sub totals, one for each tax percentage",
                                    "type": "object",
                                    "properties": {
                                        "amount": {
                                            "type": "number",
                                            "minimum": 0
                                        },
                                        "refund": {
                                            "type": "boolean",
                                            "default": false,
                                            "description": "true if amount to customer, example: on return of goods"
                                        },
                                        "taxable_amount": {
                                            "description": "Amount including tax amount",
                                            "type": "number",
                                            "minimum": 0
                                        },
                                        "net_amount": {
                                            "description": "Amount excluding tax amount",
                                            "type": "number",
                                            "minimum": 0
                                        },
                                        "tax_percentage": {
                                            "type": "number",
                                            "minimum": 0
                                        }
                                    },
                                    "required": [
                                        "amount",
                                        "taxable_amount",
                                        "net_amount",
                                        "tax_percentage"
                                    ]
                                }
                            }
                        },
                        "required": [
                            "type",
                            "amount"
                        ],
                        "additionalProperties": false
                    }
                ]
            }
        },
        "customer": {
            "description": "The person or animal owner to whom the prescription is issued.",
            "anyOf": [
                {
                    "type": "object",
                    "description": "Defines valid customer identifiers",
                    "properties": {
                        "id": {
                            "type": "object",
                            "oneOf": [
                                {
                                    "type": "object",
                                    "description": "The customer ssn",
                                    "properties": {
                                        "civic_registration_number": {
                                            "type": "string",
                                            "pattern": "^[12]{1}[90]{1}[0-9]{6}-?[0-9]{4}$",
                                            "description": "swedish personnummer 12 digits"
                                        }
                                    },
                                    "required": [
                                        "civic_registration_number"
                                    ],
                                    "additionalProperties": false
                                },
                                {
                                    "type": "object",
                                    "description": "The customer birth date",
                                    "properties": {
                                        "birth_date": {
                                            "type": "string",
                                            "pattern": "^[12]{1}[90]{1}[0-9]{6}$",
                                            "description": "birth date 10 digits, e.g 19920101"
                                        }
                                    },
                                    "required": [
                                        "birth_date"
                                    ],
                                    "additionalProperties": false
                                },
                                {
                                    "type": "object",
                                    "description": "The company registration number, when a company is the customer",
                                    "properties": {
                                        "company_registration_number": {
                                            "type": "string",
                                            "description": "company registration number used as id when the customer is a company"
                                        }
                                    },
                                    "required": [
                                        "company_registration_number"
                                    ],
                                    "additionalProperties": false
                                }
                            ]
                        }
                    }
                },
                {
                    "type": "object",
                    "description": "Defines customer information, like name, address, loyalty program.",
                    "properties": {
                        "name": {
                            "type": "string"
                        },
                        "contact": {
                            "type": "object",
                            "properties": {
                                "address": {
                                    "title": "address",
                                    "description": "An address following the convention of http://microformats.org/wiki/hcard",
                                    "type": "object",
                                    "properties": {
                                        "street_address": {
                                            "type": "string"
                                        },
                                        "extended_address": {
                                            "type": "string"
                                        },
                                        "post_box": {
                                            "type": "string"
                                        },
                                        "locality": {
                                            "type": "string"
                                        },
                                        "postal_code": {
                                            "type": "string"
                                        },
                                        "region": {
                                            "type": "string"
                                        },
                                        "country_name": {
                                            "type": "string"
                                        },
                                        "type": {
                                            "type": "object",
                                            "title": "address type",
                                            "description": "is address (physical/email) related to business, home, etc",
                                            "properties": {
                                                "type": {
                                                    "enum": [
                                                        "home",
                                                        "business"
                                                    ]
                                                }
                                            }
                                        }
                                    },
                                    "anyOf": [
                                        {
                                            "required": [
                                                "street_address"
                                            ]
                                        },
                                        {
                                            "required": [
                                                "post_box"
                                            ]
                                        }
                                    ],
                                    "required": [
                                        "locality",
                                        "postal_code"
                                    ]
                                },
                                "email": {
                                    "type": "string",
                                    "format": "email"
                                },
                                "phone": {
                                    "title": "generic phone number",
                                    "description": "generic format for phone numbers where strict format can not be enforced, use only for phone number to be displayed",
                                    "type": "string",
                                    "pattern": "^(\\(?((\\+|(00))[0-9]{1,3})\\)?)?( ?-?\\(?[0-9]+\\)?)+$"
                                }
                            },
                            "additionalProperties": false
                        },
                        "geo_location": {
                            "type": "object",
                            "title": "Geographic location (long/lat)",
                            "description": "A geographical coordinate",
                            "properties": {
                                "latitude": {
                                    "type": "number"
                                },
                                "longitude": {
                                    "type": "number"
                                }
                            },
                            "required": [
                                "latitude",
                                "longitude"
                            ]
                        }
                    },
                    "additionalProperties": false
                }
            ]
        },
        "animal": {
            "type": "object",
            "description": "Specific properties related to animal prescriptions",
            "properties": {
                "id": {
                    "type": "string",
                    "description": "identifies the animal to whom the prescription is issued"
                }
            },
            "required": [
                "id"
            ],
            "additionalProperties": false
        },
        "human": {
            "description": "Human prescription data related to high-cost reimbursement, given as previous, current and next periods.",
            "properties": {
                "high_cost": {
                    "description": "Defines properties related to high cost reimbursement",
                    "type": "object",
                    "properties": {
                        "previous_period": {
                            "type": "object",
                            "properties": {
                                "gross": {
                                    "type": "number"
                                },
                                "net": {
                                    "type": "number"
                                },
                                "start_date": {
                                    "description": "high cost period start date-time, ISO 8601 date/time format: YYYY-MM-DDThh:mm:ssTZD",
                                    "type": "string",
                                    "format": "date-time"
                                },
                                "end_date": {
                                    "description": "high cost period end date-time, ISO 8601 date/time format: YYYY-MM-DDThh:mm:ssTZD",
                                    "type": "string",
                                    "format": "date-time"
                                }
                            },
                            "required": [
                                "gross",
                                "net",
                                "start_date"
                            ],
                            "additionalProperties": false
                        },
                        "current_period": {
                            "type": "object",
                            "properties": {
                                "gross": {
                                    "type": "number"
                                },
                                "net": {
                                    "type": "number"
                                },
                                "start_date": {
                                    "description": "high cost period start date-time, ISO 8601 date/time format: YYYY-MM-DDThh:mm:ssTZD",
                                    "type": "string",
                                    "format": "date-time"
                                },
                                "end_date": {
                                    "description": "high cost period end date-time, ISO 8601 date/time format: YYYY-MM-DDThh:mm:ssTZD",
                                    "type": "string",
                                    "format": "date-time"
                                }
                            },
                            "required": [
                                "gross",
                                "net",
                                "start_date"
                            ],
                            "additionalProperties": false
                        },
                        "next_period": {
                            "type": "object",
                            "properties": {
                                "gross": {
                                    "type": "number"
                                },
                                "net": {
                                    "type": "number"
                                },
                                "start_date": {
                                    "description": "high cost period start date-time, ISO 8601 date/time format: YYYY-MM-DDThh:mm:ssTZD",
                                    "type": "string",
                                    "format": "date-time"
                                },
                                "end_date": {
                                    "description": "high cost period end date-time, ISO 8601 date/time format: YYYY-MM-DDThh:mm:ssTZD",
                                    "type": "string",
                                    "format": "date-time"
                                }
                            },
                            "required": [
                                "gross",
                                "net",
                                "start_date"
                            ],
                            "additionalProperties": false
                        },
                        "amount_left_to_reimbursement": {
                            "description": "The amount left to high cost reimbursement",
                            "type": "object",
                            "properties": {
                                "gross": {
                                    "type": "number",
                                    "minimum": 0
                                },
                                "net": {
                                    "type": "number",
                                    "minimum": 0
                                }
                            },
                            "required": [
                                "gross",
                                "net"
                            ],
                            "additionalProperties": false
                        }
                    },
                    "allOf": [
                        {
                            "required": [
                                "previous_period"
                            ]
                        },
                        {
                            "required": [
                                "current_period"
                            ]
                        },
                        {
                            "required": [
                                "next_period"
                            ]
                        }
                    ],
                    "additionalProperties": false
                }
            },
            "required": [
                "high_cost"
            ],
            "additionalProperties": false
        },
        "medications": {
            "type": "array",
            "description": "List of medications issued and their cost. Can be used on both animal and human prescriptions.",
            "items": {
                "type": "object",
                "properties": {
                    "description": {
                        "type": "string"
                    },
                    "amount": {
                        "type": "number"
                    }
                },
                "required": [
                    "description"
                ],
                "additionalProperties": false
            }
        },
        "expedition": {
            "type": "object",
            "description": "Expedition / prescription details. The format differs between pharmacies, so the user-facing part is carried as the 'details' array of strings.",
            "properties": {
                "id": {
                    "description": "expedition id, prescription id, etc. For internal use and exchange with other systems",
                    "type": "string"
                },
                "details": {
                    "description": "this is what the user will see",
                    "type": "array",
                    "minItems": 1,
                    "items": {
                        "type": "string"
                    }
                }
            },
            "required": [
                "id",
                "details"
            ]
        }
    },
    "oneOf": [
        {
            "required": [
                "animal"
            ]
        },
        {
            "required": [
                "human",
                "amount_with_benefit"
            ]
        }
    ],
    "allOf": [
        {
            "required": [
                "business_unit"
            ]
        },
        {
            "required": [
                "cashier"
            ]
        },
        {
            "required": [
                "receipt_identifier"
            ]
        },
        {
            "required": [
                "time_of_purchase"
            ]
        },
        {
            "required": [
                "amount_without_benefit"
            ]
        },
        {
            "required": [
                "amount_to_pay"
            ]
        },
        {
            "required": [
                "expedition"
            ]
        }
    ],
    "additionalProperties": false
}