Corebanq Public Docs
Invoices

Description

Overview

The Invoices module provides comprehensive functionality for managing invoices, including:

  • Creation and management of invoices with line items
  • Automatic invoice numbering with configurable formats
  • OCR processing of invoice documents
  • QR code generation and reading (Swiss QR-bill compatible)
  • PDF generation with embedded QR codes
  • Management of common receivers and senders
  • Support for multiple currencies and VAT calculations

Endpoints

Create Invoice V3

POST /v3/invoices

Create or update selector-based invoices using source and destination counterparties instead of inline address payloads.

V3 request shape:

  • source.counterparty_id and destination.counterparty_id are required.
  • Optional cp_account_id must belong to selected counterparty and be active.
  • Optional cp_address_id must be an active address on selected counterparty. If omitted, API picks active preferred billing/fallback address.
  • Request-side invoice amounts are grouped under amount, including amount.currency, and use minor units without repeating precision.
  • Request-side rate inputs are grouped under rates.
  • Item price is sent and returned in minor units.
  • Item total_price is returned in minor units.
  • amount.shipping is sent and returned in minor units.
  • rates.discount and rates.vat are rates in percent, not monetary amounts.
  • Invoice-level response amount is compact: shared currency and precision are declared once, and each monetary field is returned as a minor-unit string.
  • Item price and total_price are minor-unit strings. Use amount.currency + amount.precision for conversion: major = minor / 10^amount.precision.

Request Body:

{
  "invoice_number": "INV-V3-000001",
  "description": "Monthly services",
  "reference": "REF-2024-04",
  "status": "draft",
  "customer_id": "550e8400-e29b-41d4-a716-446655440000",
  "source": {
    "counterparty_id": "11111111-1111-1111-1111-111111111111",
    "cp_account_id": "22222222-2222-2222-2222-222222222222",
    "cp_address_id": "33333333-3333-3333-3333-333333333333"
  },
  "destination": {
    "counterparty_id": "44444444-4444-4444-4444-444444444444"
  },
  "amount": {
    "currency": "CHF",
    "shipping": "1000"
  },
  "rates": {
    "discount": 10,
    "vat": 7.70
  },
  "items": [
    {
      "title": "Service A",
      "description": "Monthly subscription",
      "quantity": 1,
      "price": "10000"
    }
  ],
  "metadata": {
    "department": "IT",
    "project_code": "P123"
  }
}

Success Response (201):

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "invoice_number": "INV-V3-000001",
  "status": "draft",
  "source": {
    "counterparty_id": "11111111-1111-1111-1111-111111111111",
    "cp_account_id": "22222222-2222-2222-2222-222222222222",
    "cp_address_id": "33333333-3333-3333-3333-333333333333"
  },
  "destination": {
    "counterparty_id": "44444444-4444-4444-4444-444444444444",
    "cp_account_id": null,
    "cp_address_id": "66666666-6666-6666-6666-666666666666"
  },
  "amount": {
    "currency": "CHF",
    "precision": 2,
    "subtotal": "10000",
    "shipping": "1000",
    "discount_amount": "1000",
    "vat_amount": "693",
    "total": "10693"
  },
  "rates": {
    "discount": 10,
    "vat": 7.7
  },
  "items": [
    {
      "id": "987fcdeb-51a2-43d7-9012-345678901234",
      "title": "Service A",
      "quantity": 1,
      "price": "10000",
      "total_price": "10000"
    }
  ]
}

Interpretation example:

  • amount.currency = "CHF"
  • amount.precision = 2
  • item price = "1050" means CHF 10.50
  • item total_price = "2100" means CHF 21.00

Create Invoice

POST /v2/invoices

Create a new invoice with automatic numbering and PDF generation.

Request Body:

{
  "description": "Monthly services",
  "status": "draft",
  "party_type": "receiver",
  "due_date": "2024-04-01T00:00:00Z",
  "currency": "CHF",
  "iban": "CH93 0076 2011 6238 5295 7",
  "customer_id": "550e8400-e29b-41d4-a716-446655440000",
  "name_from": "Sender Company AG",
  "address_from": "Bahnhofstrasse 1",
  "zip_from": "8001",
  "city_from": "Zürich",
  "country_from": "Switzerland",
  "name_to": "Receiver GmbH",
  "address_to": "Hauptstrasse 10",
  "zip_to": "3000",
  "city_to": "Bern",
  "country_to": "Switzerland",
  "shipping": 10.00,
  "discount": 5.00,
  "vat": 7.70,
  "items": [
    {
      "title": "Service A",
      "description": "Monthly subscription",
      "quantity": 1,
      "unit_price": 100.00
    }
  ],
  "active": true,
  "metadata": {
    "department": "IT",
    "project_code": "P123"
  }
}

Success Response (201):

{
  "invoice": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "invoice_number": "INV-2024-000001",
    "status": "draft",
    "total": 112.31,
    "created_at": "2024-03-21T10:00:00Z"
  },
  "items": [
    {
      "id": "987fcdeb-51a2-43d7-9012-345678901234",
      "title": "Service A",
      "quantity": 1,
      "unit_price": 100.00,
      "total": 100.00
    }
  ]
}

Error Responses:

  • 400: Invalid input data
  • 401: Unauthorized
  • 403: Insufficient permissions
  • 500: Internal server error

Process Invoice OCR

POST /v1/invoices/ocr

Extract invoice details from documents using OCR technology.

Request Body:

{
  "base64_file": "JVBERi0xLjcKCjEgMCBvYmogICUgZW50...",
  "options": {
    "language": "en",
    "extract_items": true,
    "detect_qr": true
  }
}

Success Response (200):

{
  "extracted_data": {
    "invoice_number": "INV-2024-000123",
    "date": "2024-03-21",
    "total": 112.31,
    "currency": "CHF",
    "iban": "CH93 0076 2011 6238 5295 7",
    "recipient": {
      "name": "Receiver GmbH",
      "address": "Hauptstrasse 10",
      "zip": "3000",
      "city": "Bern"
    },
    "items": [
      {
        "description": "Service A",
        "quantity": 1,
        "price": 100.00
      }
    ]
  },
  "confidence_score": 0.95
}

Error Responses:

  • 400: Invalid file format
  • 401: Unauthorized
  • 413: File too large
  • 422: Processing failed
  • 500: Internal server error

Process Invoice OCR V2

POST /v2/invoices/ocr

Extract invoice details from documents using OCR technology with automatic recipient search, draft upload creation, and draft transfer prefilling.

Request Body:

{
  "base64_file": "JVBERi0xLjcKCjEgMCBvYmogICUgZW50...",
  "customer_id": "550e8400-e29b-41d4-a716-446655440000"
}

Success Response (202):

{
  "job_id": "123e4567-e89b-12d3-a456-426614174000",
  "status": 202,
  "upload_id": "123e4567-e89b-12d3-a456-426614174002",
  "message": "Job is processing"
}

Poll GET /v2/invoices/ocr/{id} for completion. When status is 200, the response includes transfer_id, counterparty_match, counterparty_id, cp_account_id, and result.

Error Responses:

  • 400: Invalid input or missing required fields
  • 401: Unauthorized
  • 403: Insufficient permissions
  • 413: File too large
  • 500: Internal server error

Check Invoice OCR Status

GET /v1/invoices/ocr/{id}

Check the status of an OCR processing job.

Path Parameters:

  • id: Job UUID

Success Response (200):

{
  "job_id": "123e4567-e89b-12d3-a456-426614174000",
  "status": 200,
  "result": {
    "total": "112.31",
    "customer_name": "Receiver GmbH",
    "customer_email": "info@receiver.ch",
    "currency_code": "CHF",
    "currency_symbol": "CHF",
    "due_date": "2024-04-01",
    "subtotal": "100.00",
    "sales_tax_percentage": "7.7",
    "sales_tax_amount": "7.70",
    "invoice_number": "INV-2024-000123",
    "reference": "REF123",
    "bic": "BCGEVBGG",
    "iban": "CH93 0076 2011 6238 5295 7"
  }
}

Error Responses:

  • 400: Invalid job ID
  • 401: Unauthorized
  • 403: Forbidden - job doesn't belong to user
  • 404: Job not found
  • 500: Internal server error

Check Invoice OCR Status V2

GET /v2/invoices/ocr/{id}

Check the status of an OCR processing job with counterparty destination resolution.

Path Parameters:

  • id: Job UUID

Success Response (200):

{
  "job_id": "123e4567-e89b-12d3-a456-426614174000",
  "status": 200,
  "upload_id": "123e4567-e89b-12d3-a456-426614174002",
  "transfer_id": "123e4567-e89b-12d3-a456-426614174003",
  "counterparty_match": "found",
  "counterparty_id": "123e4567-e89b-12d3-a456-426614174001",
  "cp_account_id": "123e4567-e89b-12d3-a456-426614174004",
  "message": "Job completed",
  "result": {
    "total": "112.31",
    "customer_name": "Receiver GmbH",
    "customer_email": "info@receiver.ch",
    "currency_code": "CHF",
    "currency_symbol": "CHF",
    "due_date": "2024-04-01",
    "subtotal": "100.00",
    "sales_tax_percentage": "7.7",
    "sales_tax_amount": "7.70",
    "invoice_number": "INV-2024-000123",
    "reference": "REF123",
    "bic": "BCGEVBGG",
    "iban": "CH93 0076 2011 6238 5295 7"
  }
}

Processing Response (202):

{
  "job_id": "123e4567-e89b-12d3-a456-426614174000",
  "status": 202,
  "upload_id": "123e4567-e89b-12d3-a456-426614174002",
  "message": "Job is processing"
}

Failed Response (500):

{
  "job_id": "123e4567-e89b-12d3-a456-426614174000",
  "status": 500,
  "message": "Job failed"
}

Notes:

  • upload_id identifies the draft upload created for the scanned document; present while the job is processing and when complete; omitted when the job fails and draft resources are cleaned up
  • transfer_id identifies the draft transfer prefilled from OCR data (only when status is 200)
  • counterparty_match is found when an existing destination counterparty matched, or created when a new one was created (only when status is 200)
  • counterparty_id and cp_account_id identify the resolved destination selectors used by the prefilled draft transfer
  • transaction_id is a legacy customer-transaction draft identifier; new jobs use transfer_id instead
  • recipient and recipient_match are legacy fields for older jobs; new OCR jobs expose counterparty fields instead

Error Responses:

  • 400: Invalid job ID
  • 401: Unauthorized
  • 403: Forbidden - job doesn't belong to user
  • 404: Job not found
  • 500: Internal server error

Read QR Code

POST /v1/invoices/qrcode

Extract payment information from Swiss QR-bills.

Request Body:

{
  "base64_file": "JVBERi0xLjcKCjEgMCBvYmogICUgZW50...",
  "options": {
    "page": 1,
    "validate_format": true
  }
}

Success Response (200):

{
  "qr_info": {
    "iban": "CH93 0076 2011 6238 5295 7",
    "creditor": {
      "name": "Sender Company AG",
      "address": "Bahnhofstrasse 1",
      "zip": "8001",
      "city": "Zürich",
      "country": "CH"
    },
    "amount": 112.31,
    "currency": "CHF",
    "reference": "RF18539007547034",
    "message": "Invoice INV-2024-000123"
  }
}

Error Responses:

  • 400: Invalid file format or no QR code found
  • 401: Unauthorized
  • 413: File too large
  • 422: Invalid QR code format
  • 500: Internal server error

Get Invoice By ID

GET /v2/invoices/{id}

Retrieve complete invoice details including line items.

Path Parameters:

  • id: Invoice UUID

Query Parameters:

  • include_items: Include line items (default: true)
  • include_metadata: Include metadata (default: false)

Success Response (200):

{
  "invoice": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "invoice_number": "INV-2024-000001",
    "description": "Monthly services",
    "status": "draft",
    "party_type": "receiver",
    "due_date": "2024-04-01T00:00:00Z",
    "currency": "CHF",
    "iban": "CH93 0076 2011 6238 5295 7",
    "customer_id": "550e8400-e29b-41d4-a716-446655440000",
    "name_from": "Sender Company AG",
    "address_from": "Bahnhofstrasse 1",
    "zip_from": "8001",
    "city_from": "Zürich",
    "country_from": "Switzerland",
    "name_to": "Receiver GmbH",
    "address_to": "Hauptstrasse 10",
    "zip_to": "3000",
    "city_to": "Bern",
    "country_to": "Switzerland",
    "subtotal": 100.00,
    "shipping": 10.00,
    "discount": 5.00,
    "vat": 7.70,
    "total": 112.31,
    "created_at": "2024-03-21T10:00:00Z",
    "metadata": {
      "department": "IT",
      "project_code": "P123"
    }
  },
  "items": [
    {
      "id": "987fcdeb-51a2-43d7-9012-345678901234",
      "invoice_id": "123e4567-e89b-12d3-a456-426614174000",
      "title": "Service A",
      "description": "Monthly subscription",
      "quantity": 1,
      "unit_price": 100.00,
      "total": 100.00
    }
  ]
}

Error Responses:

  • 400: Invalid invoice ID format
  • 401: Unauthorized
  • 403: Insufficient permissions
  • 404: Invoice not found
  • 500: Internal server error

Get All Invoices

GET /v2/invoices

List all invoices with support for filtering, sorting, and stacking.

Query Parameters:

  • status: Filter by invoice status (draft/pending/paid/sent/overdue)
  • date_from: Start date (format: 2024-03-21T00:00:00Z)
  • date_to: End date (format: 2024-03-21T23:59:59Z)
  • currency: 3-letter currency code (e.g., CHF)
  • customer_id: Customer UUID
  • limit: Records per page (default: 10, max: 50)
  • offset: Pagination offset (default: 0)
  • sort: Sort fields with optional - prefix (e.g., -created_at,status)
  • stack: Stack by field with optional format (e.g., created_at[DD-MM-YYYY])

Query Parameters Documentation

Search Parameters

Use search.field.operator=value format for filtering:

search.status.eq=draft
search.amount.gt=1000
search.currency.in=CHF,EUR
search.active=true

Available operators:

  • eq: Equal to
  • ne: Not equal to
  • gt: Greater than
  • gte: Greater than or equal to
  • lt: Less than
  • lte: Less than or equal to
  • in: In array (comma-separated values)
  • nin: Not in array (comma-separated values)
  • like: Contains string (case-insensitive)
  • ilike: Contains string (case-sensitive)

Sort Parameters

Use sort=field for ascending or sort=-field for descending order:

sort=created_at        # ascending
sort=-amount          # descending
sort=status,-date    # multiple fields

Stack Parameters

Group results by field(s):

stack=status           # group by status
stack=currency,status  # group by currency then status

Pagination

Control the number of results:

limit=25    # items per page (default: 10, max: 100)
offset=50   # skip first 50 items

Example

/v1/invoices?search.status.in=draft,pending&search.amount.gt=1000&sort=-created_at&stack=status&limit=25

This will:

  1. Find invoices with status 'draft' or 'pending'
  2. Filter for amounts greater than 1000
  3. Sort by creation date (newest first)
  4. Group results by status
  5. Return up to 25 results per page

Sorting Examples:

sort=created_at           # Sort by created_at ascending
sort=-created_at         # Sort by created_at descending
sort=-due_date,status    # Sort by due_date descending, then status ascending

Stacking Examples:

stack=created_at[DD-MM-YYYY]     # Group by created_at, format as DD-MM-YYYY
stack=total[#,##0.00]           # Group by total, format with thousand separators
stack=status                    # Group by status as-is
stack=-currency                 # Group by currency in reverse order

Regular Response (200):

{
  "data": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "invoice_number": "INV-2024-000001",
      "status": "draft",
      "total": 112.31,
      "created_at": "2024-03-21T10:00:00Z"
    }
  ],
  "total": 100,
  "has_more": true
}

Stacked Response (200):

{
  "data": {
    "24-03-2024": [
      {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "invoice_number": "INV-2024-000001",
        "status": "draft",
        "total": 112.31,
        "created_at": "2024-03-24T10:00:00Z"
      },
      {
        "id": "123e4567-e89b-12d3-a456-426614174001",
        "invoice_number": "INV-2024-000002",
        "status": "paid",
        "total": 245.00,
        "created_at": "2024-03-24T14:30:00Z"
      }
    ],
    "23-03-2024": [
      {
        "id": "123e4567-e89b-12d3-a456-426614174002",
        "invoice_number": "INV-2024-000003",
        "status": "pending",
        "total": 89.99,
        "created_at": "2024-03-23T09:15:00Z"
      }
    ]
  },
  "total": 100,
  "has_more": true
}

Error Responses:

  • 400: Invalid query parameters
  • 401: Unauthorized
  • 403: Insufficient permissions
  • 500: Internal server error

Update Invoice

PUT /v2/invoices/{id}

Update existing invoice details and items. Supports partial updates.

Path Parameters:

  • id: Invoice UUID

Request Body:

{
  "status": "sent",
  "due_date": "2024-04-15T00:00:00Z",
  "items": [
    {
      "id": "987fcdeb-51a2-43d7-9012-345678901234",
      "quantity": 2,
      "unit_price": 95.00
    }
  ]
}

Success Response (200):

{
  "invoice": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "status": "sent",
    "due_date": "2024-04-15T00:00:00Z",
    "total": 209.62,
    "updated_at": "2024-03-21T11:00:00Z"
  }
}

Error Responses:

  • 400: Invalid invoice ID or request body
  • 401: Unauthorized
  • 403: Insufficient permissions
  • 404: Invoice not found
  • 422: Invalid status transition
  • 500: Internal server error

Delete Invoice

DELETE /v1/invoices/{id}

Remove invoice and associated items. Only draft invoices can be deleted.

Path Parameters:

  • id: Invoice UUID

Success Response (200):

{
  "message": "Invoice successfully deleted",
  "id": "123e4567-e89b-12d3-a456-426614174000"
}

Error Responses:

  • 400: Invalid invoice ID
  • 401: Unauthorized
  • 403: Insufficient permissions
  • 404: Invoice not found
  • 422: Cannot delete non-draft invoice
  • 500: Internal server error

Get Customer Invoices

GET /v1/invoices/customers/{id}

List all invoices for a specific customer with filtering options.

Path Parameters:

  • id: Customer UUID

Query Parameters:

  • status: Filter by invoice status (draft/pending/paid/sent/overdue)
  • date_from: Start date (format: 2024-03-21T00:00:00Z)
  • date_to: End date (format: 2024-03-21T23:59:59Z)
  • currency: 3-letter currency code (e.g., CHF)

Success Response (200):

{
  "customer_id": "550e8400-e29b-41d4-a716-446655440000",
  "total_invoices": 50,
  "total_amount": 5615.50,
  "currency_breakdown": {
    "CHF": 4500.00,
    "EUR": 1115.50
  },
  "invoices": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "invoice_number": "INV-2024-000001",
      "status": "paid",
      "currency": "CHF",
      "total": 112.31,
      "created_at": "2024-03-21T10:00:00Z"
    }
  ]
}

Error Responses:

  • 400: Invalid customer ID or query parameters
  • 401: Unauthorized
  • 403: Insufficient permissions
  • 404: Customer not found
  • 500: Internal server error

Get Invoice PDF

GET /v1/invoices/{id}/pdf

Generate or retrieve PDF version of an invoice with embedded QR code.

Path Parameters:

  • id: Invoice UUID

Query Parameters:

  • template: PDF template name (optional, default: "default")
  • language: Language code for PDF content (optional, default: "en")
  • include_qr: Include QR code in PDF (optional, default: true)

Success Response (200):

{
  "content": "JVBERi0xLjcKCjEgMCBvYmogICUgZW50...",
  "filename": "INV-2024-000001.pdf",
  "content_type": "application/pdf",
  "size": 123456
}

Error Responses:

  • 400: Invalid invoice ID
  • 401: Unauthorized
  • 403: Insufficient permissions
  • 404: Invoice not found
  • 422: PDF generation failed
  • 500: Internal server error

Get Next Invoice Number

GET /v1/invoices/customers/{id}/next-number

Get the next available invoice number for a customer. The number is reserved for a short period.

Path Parameters:

  • id: Customer UUID

Success Response (200):

{
  "invoice_number": "INV-20240321-000001",
  "expires_at": "2024-03-21T10:05:00Z"
}

Error Responses:

  • 400: Invalid customer ID
  • 401: Unauthorized
  • 403: Insufficient permissions
  • 500: Internal server error

On this page