{
  "openapi": "3.1.0",
  "info": {
    "title": "Invoice API",
    "version": "1.1.0",
    "summary": "Free invoices and estimates with no watermark, a free alternative to FreshBooks and Invoice Simple.",
    "description": "Create an invoice or estimate in one call and get back a link the client can open to view it and download the PDF. No account and no API key. Creating returns an ownerKey: send it as the x-owner-key header to change the invoice or mark it paid, and give it (or adminUrl) only to the person who sent the invoice. Knowing an invoice's id is enough to read it, exactly like its link. Amounts are decimal strings in the invoice's currency. Invoice does not collect payments or send email. Errors are JSON with an error sentence that says what to change. Free with no limits. Full guide: https://invoice-free.openapps.xyz/llms.txt",
    "contact": {
      "name": "OpenApps",
      "url": "https://free-apps.openapps.xyz/"
    }
  },
  "servers": [
    {
      "url": "https://functions.bounded.sh/apps/b3b80918bc912dda8c53a48d/api"
    }
  ],
  "externalDocs": {
    "description": "llms.txt",
    "url": "https://invoice-free.openapps.xyz/llms.txt"
  },
  "paths": {
    "/": {
      "get": {
        "operationId": "describe",
        "summary": "Describe the API and its routes",
        "responses": {
          "200": {
            "description": "Name, docs links and routes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "about": {
                      "type": "string"
                    },
                    "docs": {
                      "type": "string"
                    },
                    "openapi": {
                      "type": "string"
                    },
                    "routes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/invoices": {
      "post": {
        "operationId": "createInvoice",
        "summary": "Create an invoice or estimate",
        "description": "Required: from.name, to.name and at least one item with a description and a unitPrice. Returns the client link (url), the sender's private link (adminUrl), the ownerKey and the totals.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceInput",
                "required": [
                  "from",
                  "to",
                  "items"
                ]
              },
              "example": {
                "kind": "invoice",
                "from": {
                  "name": "Sam Rivera Design",
                  "email": "sam@example.com",
                  "address": "12 Harbor Street\nPortland, OR 97201"
                },
                "to": {
                  "name": "Acme Inc.",
                  "email": "billing@acme.com"
                },
                "items": [
                  {
                    "description": "Logo design",
                    "quantity": 1,
                    "unitPrice": "600.00"
                  },
                  {
                    "description": "Revisions (hours)",
                    "quantity": 2.5,
                    "unitPrice": "80"
                  }
                ],
                "currency": "USD",
                "number": "INV-0042",
                "dueDate": "2026-11-15",
                "taxRate": 8.875,
                "paymentInstructions": "Pay online at https://example.com/pay"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Created"
                },
                "example": {
                  "invoiceId": "7iXEft5NxcZMkjhd5EUR",
                  "url": "https://invoice-free.openapps.xyz/i/7iXEft5NxcZMkjhd5EUR",
                  "adminUrl": "https://invoice-free.openapps.xyz/i/7iXEft5NxcZMkjhd5EUR/admin#k=FKqZraakKUH4AogQVWittSgt",
                  "ownerKey": "FKqZraakKUH4AogQVWittSgt",
                  "kind": "invoice",
                  "number": "INV-0042",
                  "currency": "USD",
                  "subtotal": "800.00",
                  "discount": "0.00",
                  "tax": "71.00",
                  "total": "871.00",
                  "totalDisplay": "$871.00",
                  "share": "Send url to the client: they can view the invoice and download the PDF. Give adminUrl only to the person who sent it: it lets them edit it and mark it paid."
                }
              }
            }
          },
          "400": {
            "description": "Bad input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "The price on line 1 must be a number like 120.00."
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{invoiceId}": {
      "get": {
        "operationId": "getInvoice",
        "summary": "Read an invoice with its totals and status",
        "parameters": [
          {
            "name": "invoiceId",
            "in": "path",
            "required": true,
            "description": "The id in the invoice's link.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9]{8,32}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                },
                "example": {
                  "invoiceId": "7iXEft5NxcZMkjhd5EUR",
                  "url": "https://invoice-free.openapps.xyz/i/7iXEft5NxcZMkjhd5EUR",
                  "kind": "invoice",
                  "status": "unpaid",
                  "paidAt": null,
                  "number": "INV-0042",
                  "issueDate": "2026-10-18",
                  "dueDate": "2026-11-15",
                  "currency": "USD",
                  "from": {
                    "name": "Sam Rivera Design",
                    "email": "sam@example.com",
                    "hasLogo": false
                  },
                  "to": {
                    "name": "Acme Inc.",
                    "email": "billing@acme.com"
                  },
                  "items": [
                    {
                      "description": "Logo design",
                      "quantity": "1",
                      "unitPrice": "600.00",
                      "taxRate": "8.875",
                      "amount": "600.00"
                    },
                    {
                      "description": "Revisions (hours)",
                      "quantity": "2.5",
                      "unitPrice": "80.00",
                      "taxRate": "8.875",
                      "amount": "200.00"
                    }
                  ],
                  "subtotal": "800.00",
                  "discount": null,
                  "taxes": [
                    {
                      "rate": "8.875",
                      "amount": "71.00"
                    }
                  ],
                  "tax": "71.00",
                  "total": "871.00",
                  "totalDisplay": "$871.00",
                  "notes": null,
                  "paymentInstructions": "Pay online at https://example.com/pay",
                  "pdf": "Open https://invoice-free.openapps.xyz/i/7iXEft5NxcZMkjhd5EUR and press Download PDF."
                }
              }
            }
          },
          "404": {
            "description": "No such invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "No invoice with that id."
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateInvoice",
        "summary": "Change an invoice (owner key)",
        "description": "Send any field of the create body. from and to merge with what is there; items replaces the whole list; send null for taxRate or discount to remove them.",
        "parameters": [
          {
            "name": "invoiceId",
            "in": "path",
            "required": true,
            "description": "The id in the invoice's link.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9]{8,32}$"
            }
          },
          {
            "name": "x-owner-key",
            "in": "header",
            "required": true,
            "description": "The ownerKey returned when the invoice was created.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceInput"
              },
              "example": {
                "dueDate": "2026-11-30",
                "items": [
                  {
                    "description": "Logo design",
                    "quantity": 1,
                    "unitPrice": "650.00"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The changed invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                },
                "example": {
                  "invoiceId": "7iXEft5NxcZMkjhd5EUR",
                  "url": "https://invoice-free.openapps.xyz/i/7iXEft5NxcZMkjhd5EUR",
                  "kind": "invoice",
                  "status": "unpaid",
                  "paidAt": null,
                  "number": "INV-0042",
                  "issueDate": "2026-10-18",
                  "dueDate": "2026-11-15",
                  "currency": "USD",
                  "from": {
                    "name": "Sam Rivera Design",
                    "email": "sam@example.com",
                    "hasLogo": false
                  },
                  "to": {
                    "name": "Acme Inc.",
                    "email": "billing@acme.com"
                  },
                  "items": [
                    {
                      "description": "Logo design",
                      "quantity": "1",
                      "unitPrice": "600.00",
                      "taxRate": "8.875",
                      "amount": "600.00"
                    },
                    {
                      "description": "Revisions (hours)",
                      "quantity": "2.5",
                      "unitPrice": "80.00",
                      "taxRate": "8.875",
                      "amount": "200.00"
                    }
                  ],
                  "subtotal": "800.00",
                  "discount": null,
                  "taxes": [
                    {
                      "rate": "8.875",
                      "amount": "71.00"
                    }
                  ],
                  "tax": "71.00",
                  "total": "871.00",
                  "totalDisplay": "$871.00",
                  "notes": null,
                  "paymentInstructions": "Pay online at https://example.com/pay",
                  "pdf": "Open https://invoice-free.openapps.xyz/i/7iXEft5NxcZMkjhd5EUR and press Download PDF."
                }
              }
            }
          },
          "400": {
            "description": "Bad input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "The price on line 1 must be a number like 120.00."
                }
              }
            }
          },
          "401": {
            "description": "No owner key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Send the invoice's owner key in the x-owner-key header."
                }
              }
            }
          },
          "403": {
            "description": "Wrong owner key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "That owner key does not match this invoice."
                }
              }
            }
          },
          "404": {
            "description": "No such invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "No invoice with that id."
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{invoiceId}/paid": {
      "post": {
        "operationId": "markPaid",
        "summary": "Mark an invoice paid (owner key)",
        "description": "Estimates cannot be marked paid.",
        "parameters": [
          {
            "name": "invoiceId",
            "in": "path",
            "required": true,
            "description": "The id in the invoice's link.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9]{8,32}$"
            }
          },
          {
            "name": "x-owner-key",
            "in": "header",
            "required": true,
            "description": "The ownerKey returned when the invoice was created.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "date": {
                    "type": "string",
                    "format": "date",
                    "description": "The day it was paid. Default: now."
                  }
                }
              },
              "example": {
                "date": "2026-10-25"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The invoice, now paid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                },
                "example": {
                  "invoiceId": "7iXEft5NxcZMkjhd5EUR",
                  "url": "https://invoice-free.openapps.xyz/i/7iXEft5NxcZMkjhd5EUR",
                  "kind": "invoice",
                  "status": "paid",
                  "paidAt": "2026-10-25",
                  "number": "INV-0042",
                  "issueDate": "2026-10-18",
                  "dueDate": "2026-11-15",
                  "currency": "USD",
                  "from": {
                    "name": "Sam Rivera Design",
                    "email": "sam@example.com",
                    "hasLogo": false
                  },
                  "to": {
                    "name": "Acme Inc.",
                    "email": "billing@acme.com"
                  },
                  "items": [
                    {
                      "description": "Logo design",
                      "quantity": "1",
                      "unitPrice": "600.00",
                      "taxRate": "8.875",
                      "amount": "600.00"
                    },
                    {
                      "description": "Revisions (hours)",
                      "quantity": "2.5",
                      "unitPrice": "80.00",
                      "taxRate": "8.875",
                      "amount": "200.00"
                    }
                  ],
                  "subtotal": "800.00",
                  "discount": null,
                  "taxes": [
                    {
                      "rate": "8.875",
                      "amount": "71.00"
                    }
                  ],
                  "tax": "71.00",
                  "total": "871.00",
                  "totalDisplay": "$871.00",
                  "notes": null,
                  "paymentInstructions": "Pay online at https://example.com/pay",
                  "pdf": "Open https://invoice-free.openapps.xyz/i/7iXEft5NxcZMkjhd5EUR and press Download PDF."
                }
              }
            }
          },
          "400": {
            "description": "Bad input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "The price on line 1 must be a number like 120.00."
                }
              }
            }
          },
          "401": {
            "description": "No owner key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Send the invoice's owner key in the x-owner-key header."
                }
              }
            }
          },
          "403": {
            "description": "Wrong owner key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "That owner key does not match this invoice."
                }
              }
            }
          },
          "404": {
            "description": "No such invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "No invoice with that id."
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{invoiceId}/unpaid": {
      "post": {
        "operationId": "markUnpaid",
        "summary": "Mark an invoice unpaid again (owner key)",
        "parameters": [
          {
            "name": "invoiceId",
            "in": "path",
            "required": true,
            "description": "The id in the invoice's link.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9]{8,32}$"
            }
          },
          {
            "name": "x-owner-key",
            "in": "header",
            "required": true,
            "description": "The ownerKey returned when the invoice was created.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The invoice, unpaid (or overdue when past its due date)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                },
                "example": {
                  "invoiceId": "7iXEft5NxcZMkjhd5EUR",
                  "url": "https://invoice-free.openapps.xyz/i/7iXEft5NxcZMkjhd5EUR",
                  "kind": "invoice",
                  "status": "unpaid",
                  "paidAt": null,
                  "number": "INV-0042",
                  "issueDate": "2026-10-18",
                  "dueDate": "2026-11-15",
                  "currency": "USD",
                  "from": {
                    "name": "Sam Rivera Design",
                    "email": "sam@example.com",
                    "hasLogo": false
                  },
                  "to": {
                    "name": "Acme Inc.",
                    "email": "billing@acme.com"
                  },
                  "items": [
                    {
                      "description": "Logo design",
                      "quantity": "1",
                      "unitPrice": "600.00",
                      "taxRate": "8.875",
                      "amount": "600.00"
                    },
                    {
                      "description": "Revisions (hours)",
                      "quantity": "2.5",
                      "unitPrice": "80.00",
                      "taxRate": "8.875",
                      "amount": "200.00"
                    }
                  ],
                  "subtotal": "800.00",
                  "discount": null,
                  "taxes": [
                    {
                      "rate": "8.875",
                      "amount": "71.00"
                    }
                  ],
                  "tax": "71.00",
                  "total": "871.00",
                  "totalDisplay": "$871.00",
                  "notes": null,
                  "paymentInstructions": "Pay online at https://example.com/pay",
                  "pdf": "Open https://invoice-free.openapps.xyz/i/7iXEft5NxcZMkjhd5EUR and press Download PDF."
                }
              }
            }
          },
          "400": {
            "description": "Bad input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "The price on line 1 must be a number like 120.00."
                }
              }
            }
          },
          "401": {
            "description": "No owner key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Send the invoice's owner key in the x-owner-key header."
                }
              }
            }
          },
          "403": {
            "description": "Wrong owner key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "That owner key does not match this invoice."
                }
              }
            }
          },
          "404": {
            "description": "No such invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "No invoice with that id."
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "Party": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120
          },
          "email": {
            "type": "string",
            "maxLength": 200
          },
          "address": {
            "type": "string",
            "maxLength": 400,
            "description": "Line breaks are kept."
          },
          "taxId": {
            "type": "string",
            "maxLength": 60,
            "description": "Printed for the sender only."
          }
        }
      },
      "Item": {
        "type": "object",
        "required": [
          "description",
          "unitPrice"
        ],
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "quantity": {
            "type": [
              "string",
              "number"
            ],
            "description": "Up to 4 decimals. Default 1.",
            "examples": [
              2.5
            ]
          },
          "unitPrice": {
            "type": [
              "string",
              "number"
            ],
            "description": "In the invoice's currency, with no more decimals than it has.",
            "examples": [
              "120.00"
            ]
          },
          "taxRate": {
            "type": [
              "string",
              "number"
            ],
            "description": "This line's own tax percent, up to 3 decimals. Without it the invoice's taxRate applies."
          }
        }
      },
      "InvoiceInput": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "invoice",
              "estimate"
            ],
            "description": "An estimate (a quote) prints as ESTIMATE with a valid-until date and is never paid or overdue. Default invoice."
          },
          "from": {
            "$ref": "#/components/schemas/Party"
          },
          "to": {
            "$ref": "#/components/schemas/Party"
          },
          "items": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/Item"
            }
          },
          "currency": {
            "type": "string",
            "description": "ISO code. Default USD.",
            "enum": [
              "USD",
              "EUR",
              "GBP",
              "CAD",
              "AUD",
              "NZD",
              "JPY",
              "CHF",
              "SEK",
              "NOK",
              "DKK",
              "PLN",
              "CZK",
              "HUF",
              "INR",
              "SGD",
              "HKD",
              "CNY",
              "KRW",
              "MXN",
              "BRL",
              "ARS",
              "CLP",
              "COP",
              "ZAR",
              "AED",
              "ILS",
              "TRY",
              "THB",
              "IDR",
              "PHP",
              "VND"
            ]
          },
          "number": {
            "type": "string",
            "maxLength": 40,
            "description": "Default INV- (or EST-) plus 6 characters of the id."
          },
          "issueDate": {
            "type": "string",
            "format": "date",
            "description": "Default today (UTC)."
          },
          "dueDate": {
            "type": "string",
            "format": "date",
            "description": "Default none, printed as On receipt. On an estimate, the valid-until date."
          },
          "taxRate": {
            "type": [
              "string",
              "number",
              "null"
            ],
            "description": "Percent for every line without its own rate."
          },
          "discount": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "percent",
                  "amount"
                ]
              },
              "value": {
                "type": [
                  "string",
                  "number"
                ]
              }
            },
            "description": "Taken off before tax."
          },
          "notes": {
            "type": "string",
            "maxLength": 2000
          },
          "paymentInstructions": {
            "type": "string",
            "maxLength": 2000,
            "description": "How to pay. The first web address becomes a Pay now button on the client's page."
          }
        }
      },
      "Created": {
        "type": "object",
        "properties": {
          "invoiceId": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "For the client: view and download the PDF."
          },
          "adminUrl": {
            "type": "string",
            "description": "The sender's private link: edit, mark paid. Keep it private."
          },
          "ownerKey": {
            "type": "string",
            "description": "Send as x-owner-key to change the invoice. Keep it private."
          },
          "kind": {
            "type": "string",
            "enum": [
              "invoice",
              "estimate"
            ]
          },
          "number": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "subtotal": {
            "type": "string"
          },
          "discount": {
            "type": "string"
          },
          "tax": {
            "type": "string"
          },
          "total": {
            "type": "string"
          },
          "totalDisplay": {
            "type": "string"
          },
          "share": {
            "type": "string"
          }
        }
      },
      "Invoice": {
        "type": "object",
        "properties": {
          "invoiceId": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "invoice",
              "estimate"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "unpaid",
              "paid",
              "overdue",
              "estimate"
            ],
            "description": "overdue: unpaid and past its due date. estimate: an estimate, never paid or overdue."
          },
          "paidAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "number": {
            "type": "string"
          },
          "issueDate": {
            "type": "string",
            "format": "date"
          },
          "dueDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "currency": {
            "type": "string"
          },
          "from": {
            "type": "object"
          },
          "to": {
            "type": "object"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "description": {
                  "type": "string"
                },
                "quantity": {
                  "type": "string"
                },
                "unitPrice": {
                  "type": "string"
                },
                "taxRate": {
                  "type": "string"
                },
                "amount": {
                  "type": "string"
                }
              }
            }
          },
          "subtotal": {
            "type": "string"
          },
          "discount": {
            "type": [
              "object",
              "null"
            ]
          },
          "taxes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "rate": {
                  "type": "string"
                },
                "amount": {
                  "type": "string"
                }
              }
            }
          },
          "tax": {
            "type": "string"
          },
          "total": {
            "type": "string"
          },
          "totalDisplay": {
            "type": "string"
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "paymentInstructions": {
            "type": [
              "string",
              "null"
            ]
          },
          "pdf": {
            "type": "string"
          }
        }
      }
    }
  }
}
