{"id":"39a558e75a1d41a9f46dc3180566df48149820eb8835dda59358c1320a74c6b0","pubkey":"da19f1cd34beca44be74da4b306d9d1dd86b6343cef94ce22c49c6f59816e5bd","created_at":1774618333,"kind":30817,"tags":[["title","NIP-INVOICING: Structured Invoicing"],["k","30588"],["d","nip-invoicing"]],"content":"NIP-INVOICING\n=============\n\nStructured Invoicing\n----------------------\n\n`draft` `optional`\n\nOne addressable event kind for formal invoicing on Nostr. Payment recording composes with NIP-ESCROW Receipt; expense reimbursement composes with NIP-APPROVAL.\n\n> **Standalone.** This NIP works independently on any Nostr application. Invoices MAY be linked to NIP-ESCROW receipts for payment tracking and NIP-APPROVAL gates for expense approval, but NIP-INVOICING works independently as a billing record format.\n\n> **Design principle:** This event records billing state; it does not execute payments. The invoice says \"you owe me X\". Actual money moves on whatever rail the parties choose. Payment confirmation uses NIP-ESCROW Receipt (kind 30535). Expense reimbursement uses NIP-APPROVAL Gate (kind 30570).\n\n## Motivation\n\nNostr has NIP-57 for Lightning zaps and NIP-ESCROW for conditional payment coordination, but no standard mechanism for **formal invoicing**. Many real-world transactions require structured billing:\n\n- **Freelance invoicing** -- a designer completes a project and issues an invoice with line items for design, revisions, and stock assets, with `net_14` payment terms\n- **Marketplace billing** -- a seller ships goods and issues an invoice with itemised products, shipping, and tax\n- **Milestone payments** -- a construction project requires multiple partial payments against a single invoice as work progresses\n- **Expense reimbursement** -- a contractor purchases materials on behalf of a client and submits an expense claim via NIP-APPROVAL with receipt evidence\n- **P2P commerce** -- any peer-to-peer transaction where one party needs to formally request payment with a structured breakdown\n\nWithout a standard, each invoicing application invents its own format. NIP-INVOICING provides a minimal, composable primitive that any Nostr application can adopt for structured billing.\n\n## Relationship to Existing NIPs\n\n- **NIP-QUOTE (kind 30530):** Quotes propose prices before work begins; invoices bill for completed work. A quote says \"this will cost X\"; an invoice says \"you owe X for work delivered.\" They represent distinct lifecycle moments and both are needed.\n- **NIP-ESCROW Receipt (kind 30535):** Invoice payments use Receipt events with an `e` tag referencing the invoice event. This supports partial payments via multiple Receipts against the same invoice. See [Composing with NIP-ESCROW Receipt](#composing-with-nip-escrow-receipt).\n- **NIP-APPROVAL (kinds 30570-30571):** Expense reimbursement uses Approval Gates with expense line items and receipt evidence. The approver responds with an Approval Response. See [Composing with NIP-APPROVAL](#composing-with-nip-approval).\n- **NIP-EVIDENCE (kind 30578):** Receipt documentation for expense claims uses Evidence records. Expense Approval Gates reference Evidence events via `e` tags.\n- **NIP-57 (Zaps):** NIP-57 handles Lightning zap receipts for tips and donations. NIP-INVOICING handles structured billing with line items, payment terms, and partial payments. They serve different use cases: zaps are spontaneous one-click payments; invoices are formal requests with itemised breakdowns.\n- **NIP-69 (Peer-to-Peer Order Events):** NIP-69 defines buy/sell order matching for marketplaces. NIP-INVOICING handles the billing step after a transaction is agreed. An invoice MAY reference a NIP-69 order event via its `e` tag, recording the formal payment request for a matched order.\n\n## Kinds\n\n| kind  | description |\n| ----- | ----------- |\n| 30588 | Invoice     |\n\nKind 30588 is an addressable event (NIP-01).\n\n---\n\n## Invoice (`kind:30588`)\n\nPublished by a provider (seller, freelancer, contractor) as a formal request for payment. An invoice contains one or more line items, each specifying a description, quantity, unit price, and tax amount. The invoice total is carried in the `amount` tag and MUST equal the sum of all line item totals (quantity x unit_price + tax per item), minus any `discount`.\n\nInvoices are addressable; a provider can update an invoice by republishing with the same `d` tag (e.g. to revise line items after a recipient disputes the original).\n\n```json\n{\n  \"kind\": 30588,\n  \"pubkey\": \"<provider-hex-pubkey>\",\n  \"created_at\": 1709740800,\n  \"tags\": [\n    [\"d\", \"INV-2026-0042\"],\n    [\"t\", \"invoice\"],\n    [\"e\", \"<originating-event-id>\", \"wss://relay.example.com\"],\n    [\"invoice_number\", \"INV-2026-0042\"],\n    [\"amount\", \"27800\"],\n    [\"currency\", \"GBP\"],\n    [\"alt\", \"Invoice INV-2026-0042: 27800 GBP\"],\n    [\"line_item\", \"Logo design, base fee\", \"1\", \"20000\", \"4000\"],\n    [\"line_item\", \"Two revision rounds\", \"2\", \"1500\", \"600\"],\n    [\"line_item\", \"Stock image licence\", \"1\", \"200\", \"0\"],\n    [\"p\", \"<requester-hex-pubkey>\"],\n    [\"payment_terms\", \"net_14\"],\n    [\"due_date\", \"1710950400\"],\n    [\"tax_rate\", \"20\"],\n    [\"subtotal\", \"23200\"],\n    [\"tax_total\", \"4600\"]\n  ],\n  \"content\": \"\",\n  \"id\": \"<32-byte-hex>\",\n  \"sig\": \"<64-byte-hex>\"\n}\n```\n\nTags:\n\n* `d` (REQUIRED): Addressable event identifier. RECOMMENDED format: a human-readable invoice number (e.g. `INV-2026-0042`) or an application-specific identifier.\n* `t` (REQUIRED): Protocol family marker. MUST be `\"invoice\"`.\n* `e` (RECOMMENDED): References the originating event -- a NIP-15 marketplace order, a NIP-99 classified listing, a service agreement, or any application-specific event. Invoices for work agreed off-platform MAY omit the `e` tag.\n* `invoice_number` (REQUIRED): Human-readable sequential invoice identifier for the provider's accounting records. MUST be a non-empty string.\n* `amount` (REQUIRED): Total invoice amount in smallest currency unit (pence for GBP, cents for USD, satoshis for SAT).\n* `currency` (REQUIRED): ISO 4217 currency code or cryptocurrency code (e.g. `GBP`, `USD`, `EUR`, `SAT`, `BTC`).\n* `line_item` (REQUIRED, multiple): Repeatable -- one tag per billable entry. Format: `[\"line_item\", \"<description>\", \"<quantity>\", \"<unit_price>\", \"<tax>\"]`. See [Line Item Format](#line-item-format) below.\n* `p` (RECOMMENDED): Invoice recipient's hex pubkey.\n* `payment_terms` (RECOMMENDED): Payment terms code (see [Payment Terms Codes](#payment-terms-codes) below).\n* `due_date` (RECOMMENDED): Payment due date as a Unix timestamp.\n* `tax_rate` (OPTIONAL): Applicable tax rate as a percentage string (e.g. `\"20\"` for 20%).\n* `ref` (OPTIONAL): External business reference (e.g. purchase order number, project code).\n* `subtotal` (OPTIONAL): Pre-tax subtotal in smallest currency unit.\n* `tax_total` (OPTIONAL): Total tax amount in smallest currency unit.\n* `discount` (OPTIONAL): Discount amount in smallest currency unit.\n* `discount_reason` (OPTIONAL): Reason for discount (e.g. `\"early_payment\"`, `\"loyalty\"`).\n* `notes` (OPTIONAL): Additional invoice notes.\n* `expiration` (OPTIONAL): Invoice validity period -- Unix timestamp. Clients SHOULD use NIP-40 `expiration` for relay-level enforcement.\n\n**Content:** Empty string or NIP-44 encrypted JSON with extended invoice details such as provider business address, recipient billing address, bank details, or regulatory information.\n\n### Line Item Format\n\nEach `line_item` tag is a structured multi-value tag array with positional elements:\n\n```\n[\"line_item\", \"<description>\", \"<quantity>\", \"<unit_price>\", \"<tax>\"]\n```\n\n| Position | Field         | Required | Description                                                      |\n|----------|---------------|----------|------------------------------------------------------------------|\n| 1        | `description` | Yes      | Human-readable description of the work or item                   |\n| 2        | `quantity`    | Yes      | Number of units (integer or decimal string)                      |\n| 3        | `unit_price`  | Yes      | Price per unit in smallest currency unit                         |\n| 4        | `tax`         | No       | Tax amount for this line item in smallest currency unit (default: `\"0\"`) |\n\n### Payment Terms Codes\n\n| Code              | Description                                      |\n|-------------------|--------------------------------------------------|\n| `due_on_receipt`  | Payment due immediately upon invoice receipt      |\n| `net_7`           | Payment due within 7 days                         |\n| `net_14`          | Payment due within 14 days                        |\n| `net_30`          | Payment due within 30 days                        |\n| `net_60`          | Payment due within 60 days                        |\n| `net_90`          | Payment due within 90 days                        |\n| `milestone`       | Payment due upon milestone completion             |\n| `custom`          | Custom terms (details in content)                 |\n\n### Tag Reference\n\n| Tag              | Required | Multiple | Description                                |\n|------------------|----------|----------|--------------------------------------------|\n| `d`              | MUST     | No       | Addressable event identifier               |\n| `t`              | MUST     | No       | Protocol family marker                     |\n| `e`              | SHOULD   | No       | Reference to originating event             |\n| `invoice_number` | MUST     | No       | Human-readable invoice identifier          |\n| `amount`         | MUST     | No       | Total invoice amount (smallest unit)       |\n| `currency`       | MUST     | No       | Currency code                              |\n| `line_item`      | MUST     | Yes      | Itemised billable entry (positional array)  |\n| `p`              | SHOULD   | No       | Invoice recipient pubkey                   |\n| `payment_terms`  | SHOULD   | No       | Payment terms code                         |\n| `due_date`       | SHOULD   | No       | Payment due date (Unix timestamp)          |\n| `tax_rate`       | MAY      | No       | Tax rate percentage                        |\n| `ref`            | MAY      | No       | External business reference                |\n| `subtotal`       | MAY      | No       | Pre-tax subtotal                           |\n| `tax_total`      | MAY      | No       | Total tax amount                           |\n| `discount`       | MAY      | No       | Discount amount                            |\n| `discount_reason`| MAY      | No       | Reason for discount                        |\n| `notes`          | MAY      | No       | Additional invoice notes                   |\n| `expiration`     | MAY      | No       | Invoice validity period                    |\n\n### REQ Filters\n\nDiscover invoices addressed to a specific recipient:\n\n```json\n{\"kinds\": [30588], \"#p\": [\"<recipient-hex-pubkey>\"]}\n```\n\nDiscover all invoices published by a specific provider:\n\n```json\n{\"kinds\": [30588], \"authors\": [\"<provider-hex-pubkey>\"]}\n```\n\nDiscover a specific invoice by its `d` tag:\n\n```json\n{\"kinds\": [30588], \"#d\": [\"INV-2026-0042\"], \"authors\": [\"<provider-hex-pubkey>\"]}\n```\n\n> **Note:** Tags such as `invoice_number`, `payment_terms`, `line_item`, and `tax_rate` are multi-letter tags. Standard relays index only single-letter tags (`d`, `e`, `p`, `t`). Discovery SHOULD use `kinds`, `authors`, `#p`, and `#d` filters as shown above. Multi-letter tag values are available after fetching the event and SHOULD be applied as client-side filters.\n\n---\n\n## Composing with NIP-ESCROW Receipt\n\nInvoice payments are recorded using NIP-ESCROW Payment Receipt (kind 30535) with an `e` tag referencing the invoice event. An invoice payment IS a payment receipt. The Receipt already carries `payer`, `payee`, `amount`, `currency`, `trust_model`, and `settlement_proof`. No new kind is needed.\n\nMultiple Receipts MAY reference the same invoice for partial payments. The outstanding balance is calculated as:\n\n```\noutstanding = invoice.amount - sum(all kind:30535 amounts referencing this invoice)\n```\n\nClients SHOULD display the outstanding balance alongside the invoice. The sum of all Receipt amounts for an invoice MUST NOT exceed the invoice `amount`.\n\n### Full Payment Example\n\nA payer records full payment of invoice INV-2026-0042 via Lightning:\n\n```json\n{\n  \"kind\": 30535,\n  \"pubkey\": \"<payer-hex-pubkey>\",\n  \"created_at\": 1709740800,\n  \"tags\": [\n    [\"d\", \"INV-2026-0042:receipt\"],\n    [\"alt\", \"Payment receipt for invoice INV-2026-0042: 27800 GBP\"],\n    [\"e\", \"<invoice-event-id>\", \"wss://relay.example.com\"],\n    [\"payer\", \"<payer-hex-pubkey>\"],\n    [\"payee\", \"<provider-hex-pubkey>\"],\n    [\"amount\", \"27800\"],\n    [\"currency\", \"GBP\"],\n    [\"trust_model\", \"direct\"],\n    [\"settlement_proof\", \"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"]\n  ],\n  \"content\": \"\",\n  \"id\": \"<32-byte-hex>\",\n  \"sig\": \"<64-byte-hex>\"\n}\n```\n\nThe `e` tag references the Kind 30588 invoice event ID. The `d` tag RECOMMENDED format for invoice receipts is `<invoice_d_tag>:receipt` for full payments, or `<invoice_d_tag>:receipt:<sequence>` for partial payments.\n\n### Partial Payment Example (Milestone-Based)\n\nFirst milestone payment of 50000 pence against a larger invoice, paid by bank transfer:\n\n```json\n{\n  \"kind\": 30535,\n  \"pubkey\": \"<payer-hex-pubkey>\",\n  \"created_at\": 1709740800,\n  \"tags\": [\n    [\"d\", \"INV-2026-0099:receipt:001\"],\n    [\"alt\", \"Partial payment receipt for invoice INV-2026-0099: 50000 GBP (milestone 1)\"],\n    [\"e\", \"<invoice-event-id>\", \"wss://relay.example.com\"],\n    [\"payer\", \"<payer-hex-pubkey>\"],\n    [\"payee\", \"<provider-hex-pubkey>\"],\n    [\"amount\", \"50000\"],\n    [\"currency\", \"GBP\"],\n    [\"trust_model\", \"direct\"],\n    [\"settlement_proof\", \"BACS-REF-20260215-001\"]\n  ],\n  \"content\": \"\",\n  \"id\": \"<32-byte-hex>\",\n  \"sig\": \"<64-byte-hex>\"\n}\n```\n\nSecond milestone payment completing the invoice:\n\n```json\n{\n  \"kind\": 30535,\n  \"pubkey\": \"<payer-hex-pubkey>\",\n  \"created_at\": 1709827200,\n  \"tags\": [\n    [\"d\", \"INV-2026-0099:receipt:002\"],\n    [\"alt\", \"Partial payment receipt for invoice INV-2026-0099: 50000 GBP (milestone 2)\"],\n    [\"e\", \"<invoice-event-id>\", \"wss://relay.example.com\"],\n    [\"payer\", \"<payer-hex-pubkey>\"],\n    [\"payee\", \"<provider-hex-pubkey>\"],\n    [\"amount\", \"50000\"],\n    [\"currency\", \"GBP\"],\n    [\"trust_model\", \"direct\"],\n    [\"settlement_proof\", \"BACS-REF-20260301-002\"]\n  ],\n  \"content\": \"\",\n  \"id\": \"<32-byte-hex>\",\n  \"sig\": \"<64-byte-hex>\"\n}\n```\n\n### Discovery\n\nClients discover invoice payments by querying for kind 30535 events that reference the invoice event ID:\n\n```json\n{\"kinds\": [30535], \"#e\": [\"<invoice-event-id>\"]}\n```\n\n---\n\n## Composing with NIP-APPROVAL\n\nExpense reimbursement uses NIP-APPROVAL Gate (kind 30570) with expense-specific tags. A reimbursement request IS an approval request: the requester creates an Approval Gate with `line_item` tags (same format as Invoice), `e` tags linking to NIP-EVIDENCE records for receipts, and the approver responds with an Approval Response (kind 30571).\n\n### Expense Approval Gate Example\n\nA freelance photographer submits an expense claim for costs incurred during a commissioned shoot:\n\n```json\n{\n  \"kind\": 30570,\n  \"pubkey\": \"<provider-hex-pubkey>\",\n  \"created_at\": 1709740800,\n  \"tags\": [\n    [\"d\", \"EXP-2026-0042:gate:expense_claim\"],\n    [\"t\", \"approval-gate\"],\n    [\"alt\", \"Expense approval gate: 8400 GBP for design project\"],\n    [\"gate_type\", \"approval\"],\n    [\"gate_authority\", \"<client-hex-pubkey>\"],\n    [\"gate_status\", \"pending\"],\n    [\"e\", \"<originating-event-id>\", \"wss://relay.example.com\"],\n    [\"amount\", \"8400\"],\n    [\"currency\", \"GBP\"],\n    [\"line_item\", \"Stock images, Shutterstock licence x3\", \"1\", \"4500\", \"0\"],\n    [\"line_item\", \"Express courier, prototype delivery\", \"1\", \"1200\", \"0\"],\n    [\"line_item\", \"Adobe Illustrator monthly licence\", \"1\", \"2700\", \"0\"],\n    [\"e\", \"<evidence-event-id-1>\", \"wss://relay.example.com\"],\n    [\"e\", \"<evidence-event-id-2>\", \"wss://relay.example.com\"],\n    [\"expiration\", \"1710950400\"]\n  ],\n  \"content\": \"Expense claim for design project. Receipts attached as evidence records.\",\n  \"id\": \"<32-byte-hex>\",\n  \"sig\": \"<64-byte-hex>\"\n}\n```\n\nKey conventions for expense Approval Gates:\n\n* `gate_type` SHOULD be `\"approval\"`.\n* `amount` and `currency` tags carry the total reimbursement amount.\n* `line_item` tags use the same positional format as Invoice line items: `[\"line_item\", \"<description>\", \"<quantity>\", \"<unit_price>\", \"<tax>\"]`. For expenses, the `quantity` is typically `\"1\"` and `unit_price` is the expense amount.\n* `e` tags reference both the originating event (the transaction or agreement) and NIP-EVIDENCE records (kind 30578) for receipt documentation. Clients distinguish evidence references by resolving the referenced events.\n* The `amount` MUST equal the sum of all `line_item` amounts.\n\n### Expense Approval Response\n\nThe client approves the expense claim:\n\n```json\n{\n  \"kind\": 30571,\n  \"pubkey\": \"<client-hex-pubkey>\",\n  \"created_at\": 1709827200,\n  \"tags\": [\n    [\"d\", \"EXP-2026-0042:gate:expense_claim:response:<client-hex-pubkey>\"],\n    [\"t\", \"approval-response\"],\n    [\"alt\", \"Expense approval response: approved for reimbursement\"],\n    [\"e\", \"<gate-event-id>\", \"wss://relay.example.com\"],\n    [\"decision\", \"approved\"],\n    [\"p\", \"<provider-hex-pubkey>\"]\n  ],\n  \"content\": \"All receipts verified. Approved for reimbursement.\",\n  \"id\": \"<32-byte-hex>\",\n  \"sig\": \"<64-byte-hex>\"\n}\n```\n\nOnce approved, the client records reimbursement using a NIP-ESCROW Receipt (kind 30535) referencing the Approval Gate event.\n\n### Expense Categories\n\nExpense categories are application-defined. Common examples include:\n\n| Category         | Description                                   |\n|------------------|-----------------------------------------------|\n| `materials`      | Physical materials and supplies                |\n| `travel`         | Travel and transport costs                     |\n| `equipment`      | Equipment hire or purchase                     |\n| `subcontractor`  | Sub-contractor or specialist fees              |\n| `permits`        | Permits, licences, and regulatory fees         |\n| `accommodation`  | Accommodation costs                            |\n| `meals`          | Meal and sustenance costs                      |\n| `other`          | Other costs (describe in description field)    |\n\nApplications MAY define additional categories as needed for their domain.\n\n---\n\n## Protocol Flow\n\n### Overview\n\n\n![Invoice Lifecycle](https://raw.githubusercontent.com/forgesworn/nip-drafts/main/images/invoicing-1.png)\n\n```mermaid\nsequenceDiagram\n    participant Provider\n    participant Relay\n    participant Payer\n\n    Provider->>Relay: Publish Invoice (kind 30588)\n    Note right of Provider: line items, amount, payment terms\n    Relay-->>Payer: Invoice notification\n\n    Payer->>Payer: Review line items and totals\n\n    alt Full payment\n        Payer->>Relay: Publish Receipt (kind 30535, NIP-ESCROW)\n        Relay-->>Provider: Payment confirmation\n    else Partial payment (milestone)\n        Payer->>Relay: Publish Receipt 001 (kind 30535)\n        Relay-->>Provider: Partial payment recorded\n        Note over Provider,Payer: Milestone 2 completes\n        Payer->>Relay: Publish Receipt 002 (kind 30535)\n        Relay-->>Provider: Invoice fully settled\n    end\n```\n\n### Happy Path: Invoice, Review, Pay\n\n```\n  Provider                       Relay                     Requester\n      |                            |                            |\n      |-- kind:30588 Invoice ----->|                            |\n      |  (INV-2026-0042)           |                            |\n      |                            |------- notification ------>|\n      |                            |                            |\n      |                            |  Requester reviews line    |\n      |                            |  items and totals          |\n      |                            |                            |\n      |                            |<-- kind:30535 Receipt -----|\n      |<------ notification -------|    (full amount)           |\n      |                            |                            |\n      |  Provider confirms receipt |                            |\n      |                            |                            |\n```\n\n### Partial Payment Flow (Milestone-Based)\n\n```\n  Provider                       Relay                     Requester\n      |                            |                            |\n      |-- kind:30588 Invoice ----->|                            |\n      |  (payment_terms: milestone)|                            |\n      |                            |------- notification ------>|\n      |                            |                            |\n      |                            |<-- kind:30535 Receipt -----|\n      |<------ notification -------|    (amount: 50000,         |\n      |                            |     d: INV:receipt:001)    |\n      |                            |                            |\n      |           ... milestone 2 completes ...                 |\n      |                            |                            |\n      |                            |<-- kind:30535 Receipt -----|\n      |<------ notification -------|    (amount: 50000,         |\n      |                            |     d: INV:receipt:002)    |\n      |                            |                            |\n      |  Invoice fully settled     |                            |\n      |  (2 receipts)              |                            |\n      |                            |                            |\n```\n\n### Invoice Revision\n\n```\n  Provider                       Relay                     Requester\n      |                            |                            |\n      |-- kind:30588 Invoice v1 -->|                            |\n      |                            |------- notification ------>|\n      |                            |                            |\n      |                            |  Requester disputes line   |\n      |                            |  items (out of band)       |\n      |                            |                            |\n      |-- kind:30588 Invoice v2 -->|  (replaces v1; same d     |\n      |   (revised line items)     |   tag, updated content)    |\n      |                            |------- notification ------>|\n      |                            |                            |\n      |                            |<-- kind:30535 Receipt -----|\n      |<------ notification -------|    (full amount)           |\n      |                            |                            |\n```\n\n### Expense Reimbursement with Evidence\n\n```\n  Provider                       Relay                     Client\n      |                            |                            |\n      |  Provider incurs costs     |                            |\n      |  during work               |                            |\n      |                            |                            |\n      |-- kind:30578 Evidence ---->|  (receipt photos, scans)   |\n      |                            |                            |\n      |-- kind:30570 Approval ---->|                            |\n      |   Gate (with line_items    |                            |\n      |   and evidence refs)       |------- notification ------>|\n      |                            |                            |\n      |                            |  Client reviews expenses   |\n      |                            |  and evidence              |\n      |                            |                            |\n      |                            |<-- kind:30571 Response ----|\n      |<------ notification -------|    (decision: approved)    |\n      |                            |                            |\n      |                            |<-- kind:30535 Receipt -----|\n      |<------ notification -------|    (reimbursement)         |\n      |                            |                            |\n```\n\n---\n\n## Validation Rules\n\nAll validation rules for NIP-INVOICING events. Implementations MUST enforce these rules when processing invoicing events.\n\n| Rule      | Event Kind(s)              | Requirement                                                                                |\n|-----------|----------------------------|--------------------------------------------------------------------------------------------|\n| V-INV-01  | 30588 (Invoice)            | MUST include at least one `line_item` tag                                                  |\n| V-INV-02  | 30588 (Invoice)            | Each `line_item` tag MUST contain at least 4 elements: tag name, description, quantity, and unit_price |\n| V-INV-03  | 30588 (Invoice)            | `amount` MUST equal the sum of all line item totals (quantity x unit_price + tax) minus `discount` |\n| V-INV-04  | 30588 (Invoice)            | `invoice_number` MUST be a non-empty string                                                |\n| V-INV-05  | 30588 (Invoice)            | SHOULD reference an originating event via `e` tag. Invoices for work agreed off-platform MAY omit it |\n| V-INV-06  | 30588 (Invoice)            | `payment_terms` value MUST be one of the defined codes when present                        |\n| V-INV-07  | 30588 (Invoice)            | `due_date` MUST be a valid future Unix timestamp when present                              |\n| V-INV-08  | 30535 (Receipt for invoice)| `e` tag MUST reference a valid Kind 30588 invoice event                                    |\n| V-INV-09  | 30535 (Receipt for invoice)| `amount` MUST be a positive integer                                                        |\n| V-INV-10  | 30535 (Receipt for invoice)| Sum of all Receipt amounts for an invoice MUST NOT exceed the invoice `amount`             |\n\n---\n\n## Test Vectors\n\nAll examples use timestamp `1709740800` (2024-03-06T12:00:00Z) and placeholder hex pubkeys.\n\n### Kind 30588 -- Invoice\n\n```json\n{\n  \"kind\": 30588,\n  \"pubkey\": \"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2\",\n  \"created_at\": 1709740800,\n  \"tags\": [\n    [\"d\", \"INV-2026-0042\"],\n    [\"t\", \"invoice\"],\n    [\"alt\", \"Invoice INV-2026-0042: 27800 GBP\"],\n    [\"e\", \"dddd4444eeee5555ffff6666aaaa1111bbbb2222cccc3333dddd4444eeee5555\"],\n    [\"invoice_number\", \"INV-2026-0042\"],\n    [\"amount\", \"27800\"],\n    [\"currency\", \"GBP\"],\n    [\"line_item\", \"Logo design, base fee\", \"1\", \"20000\", \"4000\"],\n    [\"line_item\", \"Two revision rounds\", \"2\", \"1500\", \"600\"],\n    [\"line_item\", \"Stock image licence\", \"1\", \"200\", \"0\"],\n    [\"p\", \"b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3\"],\n    [\"payment_terms\", \"net_14\"],\n    [\"due_date\", \"1710950400\"],\n    [\"tax_rate\", \"20\"],\n    [\"subtotal\", \"23200\"],\n    [\"tax_total\", \"4600\"]\n  ],\n  \"content\": \"\",\n  \"id\": \"<32-byte-hex>\",\n  \"sig\": \"<64-byte-hex>\"\n}\n```\n\n**Calculation check:**\n- Line 1: 1 x 20000 + 4000 = 24000\n- Line 2: 2 x 1500 + 600 = 3600\n- Line 3: 1 x 200 + 0 = 200\n- Total: 24000 + 3600 + 200 = 27800\n\n### Kind 30535 -- Invoice Payment (Full, via Receipt)\n\n```json\n{\n  \"kind\": 30535,\n  \"pubkey\": \"b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3\",\n  \"created_at\": 1709740800,\n  \"tags\": [\n    [\"d\", \"INV-2026-0042:receipt\"],\n    [\"alt\", \"Payment receipt for invoice INV-2026-0042: 27800 GBP\"],\n    [\"e\", \"aaaa1111bbbb2222cccc3333dddd4444eeee5555ffff6666aaaa1111bbbb2222\"],\n    [\"payer\", \"b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3\"],\n    [\"payee\", \"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2\"],\n    [\"amount\", \"27800\"],\n    [\"currency\", \"GBP\"],\n    [\"trust_model\", \"direct\"],\n    [\"settlement_proof\", \"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"]\n  ],\n  \"content\": \"\",\n  \"id\": \"<32-byte-hex>\",\n  \"sig\": \"<64-byte-hex>\"\n}\n```\n\n### Kind 30535 -- Invoice Payment (Partial, Bank Transfer, via Receipt)\n\n```json\n{\n  \"kind\": 30535,\n  \"pubkey\": \"b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3\",\n  \"created_at\": 1709740800,\n  \"tags\": [\n    [\"d\", \"INV-2026-0099:receipt:001\"],\n    [\"alt\", \"Partial payment receipt for invoice INV-2026-0099: 50000 GBP\"],\n    [\"e\", \"aaaa1111bbbb2222cccc3333dddd4444eeee5555ffff6666aaaa1111bbbb2222\"],\n    [\"payer\", \"b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3\"],\n    [\"payee\", \"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2\"],\n    [\"amount\", \"50000\"],\n    [\"currency\", \"GBP\"],\n    [\"trust_model\", \"direct\"],\n    [\"settlement_proof\", \"BACS-REF-20260215-001\"]\n  ],\n  \"content\": \"\",\n  \"id\": \"<32-byte-hex>\",\n  \"sig\": \"<64-byte-hex>\"\n}\n```\n\n### Kind 30570 -- Expense Approval Gate\n\n```json\n{\n  \"kind\": 30570,\n  \"pubkey\": \"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2\",\n  \"created_at\": 1709740800,\n  \"tags\": [\n    [\"d\", \"EXP-2026-0042:gate:expense_claim\"],\n    [\"t\", \"approval-gate\"],\n    [\"alt\", \"Expense approval gate: 8400 GBP for design project\"],\n    [\"gate_type\", \"approval\"],\n    [\"gate_authority\", \"b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3\"],\n    [\"gate_status\", \"pending\"],\n    [\"e\", \"dddd4444eeee5555ffff6666aaaa1111bbbb2222cccc3333dddd4444eeee5555\"],\n    [\"amount\", \"8400\"],\n    [\"currency\", \"GBP\"],\n    [\"line_item\", \"Stock images, Shutterstock licence x3\", \"1\", \"4500\", \"0\"],\n    [\"line_item\", \"Express courier, prototype delivery\", \"1\", \"1200\", \"0\"],\n    [\"line_item\", \"Adobe Illustrator monthly licence\", \"1\", \"2700\", \"0\"],\n    [\"e\", \"eeee1111ffff2222aaaa3333bbbb4444cccc5555dddd6666eeee1111ffff2222\"],\n    [\"e\", \"ffff2222aaaa3333bbbb4444cccc5555dddd6666eeee1111ffff2222aaaa3333\"],\n    [\"expiration\", \"1710950400\"]\n  ],\n  \"content\": \"Expense claim for design project. Receipts attached as evidence records.\",\n  \"id\": \"<32-byte-hex>\",\n  \"sig\": \"<64-byte-hex>\"\n}\n```\n\n**Calculation check:**\n- Item 1: 4500\n- Item 2: 1200\n- Item 3: 2700\n- Total: 4500 + 1200 + 2700 = 8400\n\n---\n\n## Security Considerations\n\n### Invoice Fraud\n\nProviders MUST only publish invoices for transactions they are a participant in. Clients SHOULD verify that the invoice publisher's pubkey matches a known participant in the referenced transaction. Applications MAY reject invoices from non-participants.\n\n### Double Payment\n\nClients tracking invoice payments MUST maintain a running total of all Kind 30535 Receipt events referencing a given invoice. The sum of `amount` values MUST NOT exceed the invoice `amount`. Clients SHOULD warn users when a payment would exceed the outstanding balance.\n\n### Expense Claim Manipulation\n\nExpense Approval Gates without evidence references carry lower trust. Applications SHOULD require NIP-EVIDENCE records for expenses above a configurable threshold. The NIP-APPROVAL workflow provides a formal mechanism for recipients to review and approve or reject expense claims before reimbursement.\n\n### Tax Calculation Integrity\n\nThe `amount` tag on Kind 30588 is the authoritative total. Clients SHOULD independently verify that line item calculations match the stated total. Discrepancies SHOULD be flagged to the recipient before payment.\n\n### Multi-Currency Considerations\n\nAll amounts within a single invoice MUST be in the same currency (as specified by the `currency` tag). If a provider needs to bill in multiple currencies, they MUST publish separate invoices. Receipt `currency` SHOULD match the invoice currency; cross-currency payments require agreement between parties and MAY use the Receipt content field to document the exchange rate.\n\n---\n\n## Relay Recommendations\n\n| Event Kind                   | Recommended Retention            | Rationale                                 |\n|------------------------------|----------------------------------|-------------------------------------------|\n| 30588 (Invoice)              | Long-term (application-specific) | Financial record-keeping                  |\n\nInvoicing events are financial records. The appropriate retention period depends on the jurisdiction and application context. Applications SHOULD advise users on local record-keeping requirements. NIP-ESCROW Receipt events (kind 30535) used for invoice payments follow the retention guidance in NIP-ESCROW.\n\n---\n\n## Use Cases\n\n### Freelancing and Creative Services\n\nA graphic designer completes a branding project and publishes a Kind 30588 invoice with line items for design work, revision rounds, and stock image licences. The client pays via Lightning and records the payment with a Kind 30535 Receipt including the preimage as settlement proof.\n\n### Marketplace Commerce\n\nA NIP-15 marketplace seller ships goods and issues a Kind 30588 invoice referencing the NIP-15 order event. Line items cover each product, shipping, and applicable tax. The buyer records payment with a Kind 30535 Receipt.\n\n### P2P Commerce\n\nTwo individuals agree on a transaction via Nostr DMs. The seller publishes a Kind 30588 invoice referencing the DM thread. The buyer pays and records the payment with a Kind 30535 Receipt. Both parties have a verifiable billing record.\n\n### Construction and Milestone Payments\n\nA builder issues a Kind 30588 invoice with `payment_terms: milestone` for a renovation project. The client makes partial payments via Kind 30535 Receipts as each milestone is completed. Both parties can track the outstanding balance at any time.\n\n### Expense Reimbursement\n\nA freelance photographer travelling for a commissioned shoot publishes NIP-EVIDENCE records for travel, accommodation, and equipment receipts. They then create a NIP-APPROVAL Gate (kind 30570) with expense line items and evidence references. The client reviews and approves via a Kind 30571 Response, then reimburses via a Kind 30535 Receipt.\n\n---\n\n## Dependencies\n\n* [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md): Basic protocol flow, addressable events\n* [NIP-40](https://github.com/nostr-protocol/nips/blob/master/40.md): Expiration timestamps (invoice validity)\n* [NIP-44](https://github.com/nostr-protocol/nips/blob/master/44.md): Versioned encrypted payloads (private invoice details)\n* NIP-ESCROW: Payment Receipt (kind 30535) for recording invoice payments\n* NIP-APPROVAL: Approval Gate (kind 30570) and Response (kind 30571) for expense reimbursement\n* NIP-EVIDENCE: Evidence Record (kind 30578) for expense receipt documentation\n\n## Reference Implementation\n\nNo public reference implementation exists yet. Implementors SHOULD refer to the kind definitions above.\n\nA minimal implementation requires:\n\n1. A Nostr client that supports addressable event publishing.\n2. Invoice rendering logic -- parsing `line_item` tag arrays and computing totals for display.\n3. Payment tracking -- querying Kind 30535 Receipts by `e` tag reference to the invoice event and computing outstanding balances.\n4. (Optional) Expense reimbursement -- creating NIP-APPROVAL Gates with expense line items and NIP-EVIDENCE references.","sig":"bdf63c7b34aa1c443cf0668b43187d3e501591972ac7516694343af51145edbb47b2a77c0f7c800e95ed1584c5a8f72a3954e96a5810ac7c59a05b6a60336487"}