Expenses
Expenses
Received supplier invoices and expense records.
The Expense object
Attributes
{
"id": "exp_6595a27b5d35015c3ef0c3fd",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"supplier_id": "sup_6595a27b5d35015c3ef0c3fd",
"type": "invoice",
"is_draft": false,
"voided_at": null,
"supplier": {
"name": "Orbital Power Systems GmbH",
"address": "Energieweg 8",
"address_2": null,
"post_code": "10115",
"city": "Berlin",
"state": null,
"country": "Germany",
"country_code": "DE",
"tax_number": "DE987654321",
"company_number": "HRB 98765",
"email": "accounts@orbital-power.example",
"phone": "+493012345678",
"peppol_id": "0088:9876543210982",
"is_tax_subject": true
},
"supplier_document_number": "OPS-2025-001",
"date": "2025-10-03",
"date_received": "2025-10-03",
"date_due": "2025-11-02",
"date_service": null,
"date_service_to": null,
"currency_code": "EUR",
"transaction_type": "domestic",
"reference": "DE00-2025-001",
"note": "Ground facility maintenance — March billing period",
"summary_classification": null,
"items": [
{
"name": "Ground facility maintenance",
"description": "Monthly ground facility maintenance",
"quantity": 1,
"unit": "service",
"classification": "service",
"price": 100,
"gross_price": 119,
"discounts": [],
"taxes": [
{
"rate": 19,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100
}
],
"total": 100,
"total_with_tax": 119,
"total_tax": 19
}
],
"taxes": [
{
"rate": 19,
"base": 100,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100,
"reverse_charge": false
}
],
"total": 100,
"total_with_tax": 119,
"total_discount": 0,
"total_paid": 0,
"total_due": 119,
"paid_in_full": false,
"exchange_rate": null,
"attachment_count": 1,
"has_attachment": true,
"metadata": {
"source": "manual"
},
"created_at": "2025-10-03T08:00:00.000Z",
"updated_at": "2025-10-03T08:00:00.000Z"
}Create expense
/expensesThis is the recommended endpoint for normal expense creation. Use it when Space Invoices should validate the supplied totals, tax summaries, and line items, then apply supplier handling, payment tracking initialization, and lifecycle rules.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Body parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.create({
supplier: {
name: "Office Supplies Ltd",
tax_number: "SI12345678",
country_code: "SI"
},
supplier_document_number: "2025-0417",
date: "2025-10-03",
total: 100,
total_with_tax: 122,
taxes: [
{
rate: 22,
base: 100,
amount: 22
}
]
}, {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"id": "exp_9595a27b5d35015c3ef0c400",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"supplier_id": null,
"type": "invoice",
"is_draft": false,
"voided_at": null,
"supplier": {
"name": "Office Supplies Ltd",
"tax_number": "SI12345678",
"country_code": "SI"
},
"supplier_document_number": "2025-0417",
"date": "2025-10-03",
"date_received": "2025-10-03",
"date_due": null,
"date_service": null,
"date_service_to": null,
"currency_code": "EUR",
"transaction_type": "domestic",
"reference": "DE00-2025-001",
"note": null,
"summary_classification": null,
"items": [],
"taxes": [
{
"rate": 22,
"base": 100,
"amount": 22,
"is_deductible": true,
"deductible_percentage": 100
}
],
"total": 100,
"total_with_tax": 122,
"total_discount": 0,
"total_paid": 0,
"total_due": 122,
"paid_in_full": false,
"exchange_rate": null,
"attachment_count": 0,
"has_attachment": false,
"metadata": {
"source": "manual"
},
"created_at": "2025-10-03T08:00:00.000Z",
"updated_at": "2025-10-04T08:00:00.000Z"
}Create expense with pre-calculated totals
/expenses/customAdvanced endpoint for importing expenses that already have authoritative pre-calculated totals. Do not use this for normal expense creation. Prefer the standard create endpoint unless your integration must preserve exact external totals from an ERP, OCR, migration, or accounting system.
The caller provides document totals, item totals, and tax summaries directly.
The persistence, supplier handling, payment tracking initialization, and lifecycle rules are identical to the standard create endpoint.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Body parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.createCustom({
supplier: {
name: "Office Supplies Ltd",
tax_number: "SI12345678",
country_code: "SI"
},
supplier_document_number: "2025-0417",
date: "2025-10-03",
total: 100,
total_with_tax: 122,
taxes: [
{
rate: 22,
base: 100,
amount: 22
}
]
}, {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"id": "exp_9595a27b5d35015c3ef0c400",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"supplier_id": null,
"type": "invoice",
"is_draft": false,
"voided_at": null,
"supplier": {
"name": "Office Supplies Ltd",
"tax_number": "SI12345678",
"country_code": "SI"
},
"supplier_document_number": "2025-0417",
"date": "2025-10-03",
"date_received": "2025-10-03",
"date_due": null,
"date_service": null,
"date_service_to": null,
"currency_code": "EUR",
"transaction_type": "domestic",
"reference": "DE00-2025-001",
"note": null,
"summary_classification": null,
"items": [],
"taxes": [
{
"rate": 22,
"base": 100,
"amount": 22,
"is_deductible": true,
"deductible_percentage": 100
}
],
"total": 100,
"total_with_tax": 122,
"total_discount": 0,
"total_paid": 0,
"total_due": 122,
"paid_in_full": false,
"exchange_rate": null,
"attachment_count": 0,
"has_attachment": false,
"metadata": {
"source": "manual"
},
"created_at": "2025-10-03T08:00:00.000Z",
"updated_at": "2025-10-04T08:00:00.000Z"
}Backfill expense recognition entries
/expenses/recognition/backfillBackfill expense recognition entries
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Body parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.backfillExpenseRecognition({
date_from: "2026-01-01",
date_to: "2026-03-31",
dry_run: true,
limit: 100
}, {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"processed_expenses": 0,
"generated_entries": 0,
"dry_run": true,
"next_cursor": "next-cursor"
}Start expense recognition from a document file
/expenses/recognitionsAutomatic expense recognition supports PDFs up to 8 pages. Split a larger PDF into smaller documents before trying again.
Accepts one supplier invoice (PDF, JPEG, PNG, or WebP), creates an invoice-only draft expense with creation_source=ocr, and enqueues an async recognition job. For sandbox entities, no provider is called and no usage is charged: the submitted file is not stored and is replaced by a clearly marked deterministic demo invoice; the response exposes simulation_mode=sandbox_demo.
Returns 202 Accepted with the job, expense, and file identifiers. Recognition is asynchronous in live mode; poll GET /expenses/recognitions/{id} for status. Terminal success is ready_for_review or needs_attention; terminal failure is failed, with safe error_code and error_message fields.
Parsed document and line amounts are checked against the standard expense calculation before applying extraction. A disagreement keeps the draft unchanged and stores the extraction with needs_attention for review. Critical identity, required-field, confidence, document-type, and questionable financial warnings also require review and prevent unsafe automatic application.
Payment suggestions from OCR are advisory only and never mark the expense paid or create payments. Failed provider attempts record zero customer usage. Automatic provider attempts and a permitted customer retry share the same job; billable customer usage is recorded once only after a successful terminal result.X-Request-Id provides account/entity-scoped replay and fails closed with 409 Conflict when reused for different file content.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Optional idempotency key. Reusing it with the same entity and identical file replays the original result; reusing it with different file content fails with 409 Conflict.
Body parameters
Supplier invoice PDF or image
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
import fs from 'fs';
const sdk = new SpaceInvoices('YOUR_API_KEY');
// Read file as Buffer
const fileBuffer = fs.readFileSync('/path/to/image.png');
const file = new File([fileBuffer], 'image.png', { type: 'image/png' });
const response = await sdk.expenses.createRecognition({
file
}, { entity_id: 'YOUR_ENTITY_ID' });
console.log(response);Returns
{
"job": {
"id": "erj_6595a27b5d35015c3ef0c3fd",
"entity_id": "entity-id",
"expense_id": "expense-id",
"file_metadata_id": "file-metadata-id",
"status": "queued",
"provider": "provider",
"model": "model",
"parser_version": "parser-version",
"attempts": 0,
"max_attempts": 0,
"pages_processed": 0,
"page_count": 0,
"warnings": [
{
"code": "missing_required_field",
"field": "field",
"message": "message"
}
],
"provenance": {
"provider": "mistral",
"model": "model",
"parser_version": "parser-version",
"pages_processed": 0,
"doc_size_bytes": 0,
"fields": [
{
"field": "field",
"page": 0,
"confidence": 0,
"source": "annotation",
"note": "note"
}
]
},
"reconciliation": {
"is_reconciled": true,
"expected_total": 0,
"expected_total_with_tax": 0,
"expected_tax": 0,
"reported_total": 0,
"reported_total_with_tax": 0,
"reported_tax": 0,
"differences": [
{
"field": "field",
"expected": 0,
"reported": 0,
"delta": 0
}
]
},
"payment_suggestion": {
"status": "paid",
"amount": 0,
"date": "date",
"method": "method",
"evidence": [
"evidence"
],
"confidence": 0,
"is_partial": true
},
"extracted_draft": {
"type": "invoice",
"supplier": {
"name": "name",
"email": "user@example.com",
"address": "address",
"address_2": "address-2",
"post_code": "post-code",
"city": "city",
"state": "state",
"country": "country",
"country_code": "country-code",
"tax_number": "tax-number",
"company_number": "company-number",
"phone": "phone",
"peppol_id": "peppol-id",
"bank_accounts": [
{
"iban": "iban",
"bic": "bic",
"bank_name": "bank-name",
"account_number": "account-number",
"currency_code": "currency-code"
}
],
"is_tax_subject": true
},
"supplier_document_number": "supplier-document-number",
"date": "date",
"date_received": "date-received",
"date_due": "date-due",
"date_service": "date-service",
"date_service_to": "date-service-to",
"currency_code": "currency-code",
"transaction_type": "domestic",
"reference": "reference",
"note": "note",
"items": [
{
"name": "name",
"description": "description",
"quantity": 0,
"unit": "unit",
"classification": "product",
"price": 0,
"gross_price": 0,
"discounts": [
{
"value": 0,
"type": "percent"
}
],
"taxes": [
{
"rate": 0,
"amount": 0,
"reverse_charge": true,
"is_deductible": true,
"deductible_percentage": 0
}
],
"total": 0,
"total_with_tax": 0,
"total_tax": 0
}
],
"taxes": [
{
"rate": 0,
"base": 0,
"amount": 0,
"reverse_charge": true,
"is_deductible": true,
"deductible_percentage": 0
}
],
"total": 0,
"total_with_tax": 0,
"total_discount": 0,
"summary_classification": "product"
},
"error_code": "error-code",
"error_message": "error-message",
"request_id": "request-id",
"source_filename": "source-filename",
"source_mime_type": "source-mime-type",
"source_bytes": 0,
"source_content_sha256": "source-content-sha256",
"simulation_mode": "sandbox_demo",
"source_replaced": true,
"expense_updated_at_snapshot": "2025-01-15T10:30:00.000Z",
"queued_at": "2025-01-15T10:30:00.000Z",
"started_at": "2025-01-15T10:30:00.000Z",
"completed_at": "2025-01-15T10:30:00.000Z",
"created_at": "2025-01-15T10:30:00.000Z",
"updated_at": "2025-01-15T10:30:00.000Z"
},
"expense_id": "expense-id",
"file_metadata_id": "file-metadata-id",
"status": "queued"
}Create or rotate expense inbound email address
/expenses/inbound-emailCreates the entity's inbound email address, or issues a new one when an address already exists. Rotation invalidates the previous address immediately; mail sent to it afterwards is not accepted.
Every supported attachment (PDF, JPEG, PNG or WebP) forwarded to the entity's private inbound address becomes a draft expense. Attachments are recognised automatically when expense recognition is available to the entity; otherwise the draft expense is saved with the attachment so it can be completed manually. Anyone who knows the address can send to it, so treat it like a password: rotate it if it leaks, which invalidates the previous address immediately.
Requires permission to manage entity settings. Responds with 503 when expense inbound email is not configured on this deployment and 403 when it is hidden for the entity's white label.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.rotateExpenseInboundEmail({
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"available": true,
"enabled": true,
"address": "k3m7q2x9v5b8n4c6d1f0hjwy@invoices.example.com",
"created_at": "2026-10-05T09:30:00.000Z"
}List expenses
/expensesRetrieve a paginated list of expenses with optional filtering.
Supports cursor-based pagination, full-text search across supplier snapshot and document fields, and suite-standard JSON query filters for date, totals, payment state, and supplier snapshot data. Filter expenses that contain a saved catalog item with {"items.item_id":"item_..."}.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Query parameters
Number of results per request.
Default: 10
Opaque cursor to fetch the next page of results. Reuse only with the same effective ordering. Use the value from pagination.next_cursor in the previous response.
Opaque cursor to fetch the previous page of results. Reuse only with the same effective ordering. Use the value from pagination.prev_cursor in the previous response.
Whether to include the total count of items in pagination.total.
Default is true.
When false, pagination.total returns -1 for better performance.
Filter expenses by whether at least one attachment exists.
JSON query object for filtering results. Supports MongoDB-style operators.
Array columns (such as an item's categories) compare as sets: a direct value asks whether the list contains it, contains takes an array and requires all of them, in matches any of them, and notIn matches none. Scalar operators such as gt do not apply and are ignored.
Supported operators:
- equals or direct value - Exact match (default)
- gte - Greater than or equal
- lte - Less than or equal
- gt - Greater than
- lt - Less than
- in - Value in array
- notIn - Value not in array
- contains - String contains (case-insensitive)
- startsWith - String starts with
- endsWith - String ends with
- between - Value between two numbers/dates [min, max]
Allowed fields: id, number, type, is_draft, voided_at, deleted_at, supplier_id, supplier, supplier_document_number, date, date_received, date_due, date_service, date_service_to, currency_code, transaction_type, reference, note, summary_classification, total, total_with_tax, total_paid, total_due, paid_in_full, created_at, updated_at, metadata, items.item_id
Examples:
- {"total": {"gte": 1000}} - Invoices over 1000
- {"customer.name": {"contains": "Acme"}} - Customer name contains "Acme"
- {"date": {"between": ["2025-01-01", "2025-12-31"]}} - Date range
Sort by one field or provide a repeated array for multi-column ordering. Prefix a field with - for descending order. When paginating, reuse cursors only with the same effective ordering.
Full-text search query to filter results across multiple fields.
Searches are case-insensitive and match partial strings.
Searches across all text fields including names, descriptions, addresses, and metadata values.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.list({
limit: 20,
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
Pagination metadata including cursors and result counts
{
"data": [
{
"id": "exp_6595a27b5d35015c3ef0c3fd",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"supplier_id": "sup_6595a27b5d35015c3ef0c3fd",
"type": "invoice",
"is_draft": false,
"voided_at": null,
"supplier": {
"name": "Orbital Power Systems GmbH",
"address": "Energieweg 8",
"address_2": null,
"post_code": "10115",
"city": "Berlin",
"state": null,
"country": "Germany",
"country_code": "DE",
"tax_number": "DE987654321",
"company_number": "HRB 98765",
"email": "accounts@orbital-power.example",
"phone": "+493012345678",
"peppol_id": "0088:9876543210982",
"is_tax_subject": true
},
"supplier_document_number": "OPS-2025-001",
"date": "2025-10-03",
"date_received": "2025-10-03",
"date_due": "2025-11-02",
"date_service": null,
"date_service_to": null,
"currency_code": "EUR",
"transaction_type": "domestic",
"reference": "DE00-2025-001",
"note": "Ground facility maintenance — March billing period",
"summary_classification": null,
"items": [
{
"name": "Ground facility maintenance",
"description": "Monthly ground facility maintenance",
"quantity": 1,
"unit": "service",
"classification": "service",
"price": 100,
"gross_price": 119,
"discounts": [],
"taxes": [
{
"rate": 19,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100
}
],
"total": 100,
"total_with_tax": 119,
"total_tax": 19
}
],
"taxes": [
{
"rate": 19,
"base": 100,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100,
"reverse_charge": false
}
],
"total": 100,
"total_with_tax": 119,
"total_discount": 0,
"total_paid": 0,
"total_due": 119,
"paid_in_full": false,
"exchange_rate": null,
"attachment_count": 1,
"has_attachment": true,
"metadata": {
"source": "manual"
},
"created_at": "2025-10-03T08:00:00.000Z",
"updated_at": "2025-10-03T08:00:00.000Z"
},
{
"id": "exp_7595a27b5d35015c3ef0c3fe",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"supplier_id": "sup_6595a27b5d35015c3ef0c3fd",
"type": "invoice",
"is_draft": false,
"voided_at": null,
"supplier": {
"name": "Orbital Power Systems GmbH",
"address": "Energieweg 8",
"address_2": null,
"post_code": "10115",
"city": "Berlin",
"state": null,
"country": "Germany",
"country_code": "DE",
"tax_number": "DE987654321",
"company_number": "HRB 98765",
"email": "accounts@orbital-power.example",
"phone": "+493012345678",
"peppol_id": "0088:9876543210982",
"is_tax_subject": true
},
"supplier_document_number": "AP-CUSTOM-001",
"date": "2025-10-03",
"date_received": "2025-10-03",
"date_due": "2025-11-02",
"date_service": null,
"date_service_to": null,
"currency_code": "EUR",
"transaction_type": "domestic",
"reference": "DE00-2025-001",
"note": "Supplier provided totals only",
"summary_classification": "service",
"items": [],
"taxes": [
{
"rate": 19,
"base": 45.22,
"amount": 8.59,
"is_deductible": true,
"deductible_percentage": 100,
"reverse_charge": false
},
{
"rate": 0,
"base": 125.63,
"amount": 0,
"is_deductible": true,
"deductible_percentage": 100,
"reverse_charge": false
}
],
"total": 170.85,
"total_with_tax": 179.44,
"total_discount": 0,
"total_paid": 0,
"total_due": 179.44,
"paid_in_full": false,
"exchange_rate": null,
"attachment_count": 0,
"has_attachment": false,
"metadata": {
"source": "manual"
},
"created_at": "2025-10-03T08:00:00.000Z",
"updated_at": "2025-10-04T08:00:00.000Z"
}
],
"pagination": {
"total": 2,
"next_cursor": null,
"prev_cursor": null,
"has_more": false
}
}Export expenses to Excel
/expenses/exportExport up to 10,000 entity-scoped supplier invoice expenses to an Excel workbook. Supports an optional date range of up to one year and lets callers filter by document date (the default) or received date; when the selected date is missing, filtering falls back to the other date. The workbook includes document type, trusted source provenance (including completed legacy migrations), supplier snapshots with country-code fallback, summary product/service classification, payment state and amount due, original totals and tax amounts in each expense currency, and separately labeled converted totals and tax amounts in the entity currency when currency conversion applies. Narrow the date range if the export exceeds the row limit.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Query parameters
Export format. Expense exports currently support Excel workbooks only.
Possible values: "xlsx"
Date used to apply date_from and date_to. document (default) uses the document date and falls back to the received date; received uses the received date and falls back to the document date.
Possible values: "document", "received"
Optional inclusive lower bound for the selected expense date basis. The date range cannot exceed one year.
Optional inclusive upper bound for the selected expense date basis. The date range cannot exceed one year.
Language for workbook headers. Defaults to the entity locale when omitted.
Possible values: "en", "de", "sl", "it", "fr", "es", "pt", "nl", "pl", "hr", "sv", "fi", "et", "bg", "cs", "sk", "nb", "is", "hu"
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const blob = await sdk.expenses.exportExpenses({
format: "xlsx"
}, {
entity_id: "YOUR_ENTITY_ID"
});
const arrayBuffer = await blob.arrayBuffer();
const { writeFile } = await import('node:fs/promises');
await writeFile('download.bin', Buffer.from(arrayBuffer));
console.log('Saved download.bin');Get expenses by financial category
/expenses/reportReturn finalized expense net amounts grouped by financial category. Depending on expense-recognition settings and line overrides, recognized amounts use document dates or generated daily service-period schedules.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Query parameters
Report start date in YYYY-MM-DD format. Must be the first calendar day of a month.
Report end date in YYYY-MM-DD format. Must be the final calendar day of a month.
recognized returns expense recognized inside each period. deferred returns the remaining future expense balance at the end of each period.
Possible values: "recognized", "deferred"
Default: "recognized"
Report grouping dimension.
Possible values: "financial_category"
Default: "financial_category"
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.getExpenseCategoryReport({
date_from: "2026-01-01",
date_to: "2026-12-31"
}, {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"basis": "recognized",
"group_by": "financial_category",
"calculation_mode": "recognition_entries",
"periods": [
{
"period": "2026-01",
"date_from": "2026-01-01",
"date_to": "2026-01-31"
},
{
"period": "2026-02",
"date_from": "2026-02-01",
"date_to": "2026-02-28"
}
],
"series": [
{
"key": "fcat_office",
"financial_category_id": "fcat_office",
"name": "Office expenses",
"color": "#2563eb",
"values": [
1200,
850
],
"total": 2050
},
{
"key": "uncategorized",
"financial_category_id": null,
"name": "Uncategorized",
"color": null,
"values": [
50,
125
],
"total": 175
}
],
"totals": [
1250,
975
],
"total": 2225,
"currency_code": "EUR",
"date_from": "2026-01-01",
"date_to": "2026-02-28"
}Get expense recognition settings
/expenses/recognition/settingsGet expense recognition settings
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.getRecognitionSettings({
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"default_method": "service_period_daily"
}Get expense inbound email address
/expenses/inbound-emailReturns the entity's expense inbound email address and whether the feature is available.
Every supported attachment (PDF, JPEG, PNG or WebP) forwarded to the entity's private inbound address becomes a draft expense. Attachments are recognised automatically when expense recognition is available to the entity; otherwise the draft expense is saved with the attachment so it can be completed manually. Anyone who knows the address can send to it, so treat it like a password: rotate it if it leaks, which invalidates the previous address immediately.available is false when inbound email is not configured on this deployment or is hidden for the entity's white label; in that case enabled is false and address is null.
Requires permission to create documents for the entity, because the address itself lets its holder create expenses.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.getExpenseInboundEmail({
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"available": true,
"enabled": true,
"address": "k3m7q2x9v5b8n4c6d1f0hjwy@invoices.example.com",
"created_at": "2026-10-05T09:30:00.000Z"
}List expense inbound email messages
/expenses/inbound-email/messagesLists messages received on the entity's inbound addresses, newest first, with the outcome for each attachment (created expense, recognition job, or why it was skipped). Messages are kept for 90 days; older messages are never returned and are purged from this log (created expenses are not affected). Supports cursor pagination.
Every supported attachment (PDF, JPEG, PNG or WebP) forwarded to the entity's private inbound address becomes a draft expense. Attachments are recognised automatically when expense recognition is available to the entity; otherwise the draft expense is saved with the attachment so it can be completed manually. Anyone who knows the address can send to it, so treat it like a password: rotate it if it leaks, which invalidates the previous address immediately.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Query parameters
Number of results per request.
Default: 10
Opaque cursor to fetch the next page of results. Reuse only with the same effective ordering. Use the value from pagination.next_cursor in the previous response.
Opaque cursor to fetch the previous page of results. Reuse only with the same effective ordering. Use the value from pagination.prev_cursor in the previous response.
Whether to include the total count of items in pagination.total.
Default is true.
When false, pagination.total returns -1 for better performance.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.listExpenseInboundEmailMessages(undefined, {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
Pagination metadata including cursors and result counts
{
"data": [
{
"id": "eim_6595a27b5d35015c3ef0c3fd",
"from_email": "accountant@example.com",
"subject": "Fwd: October supplier invoices",
"status": "processed",
"reject_reason": null,
"attachments": [
{
"index": 0,
"filename": "invoice-1042.pdf",
"mime_type": "application/pdf",
"bytes": 48321,
"mode": "ocr",
"expense_id": "exp_6595a27b5d35015c3ef0c3fd",
"recognition_job_id": "erj_6595a27b5d35015c3ef0c3fd",
"reason": null
},
{
"index": 1,
"filename": "notes.txt",
"mime_type": "text/plain",
"bytes": 120,
"mode": "skipped",
"expense_id": null,
"recognition_job_id": null,
"reason": "unsupported_type"
}
],
"received_at": "2026-10-05T09:30:00.000Z",
"processed_at": "2026-10-05T09:30:04.000Z"
},
{
"id": "eim_6595a27b5d35015c3ef0c3fe",
"from_email": "supplier@example.net",
"subject": "Invoice",
"status": "rejected",
"reject_reason": "no_attachments",
"attachments": [],
"received_at": "2026-10-04T14:12:00.000Z",
"processed_at": "2026-10-04T14:12:00.000Z"
}
],
"pagination": {
"total": 2,
"next_cursor": null,
"prev_cursor": null,
"has_more": false
}
}Get expense recognition job by ID
/expenses/recognitions/{id}Returns recognition job status, extraction results, warnings, reconciliation, and advisory payment suggestion. Entity-scoped.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Expense recognition job ID
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.getRecognition("erj_6595a27b5d35015c3ef0c3fd", {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
Recognition job ID
{
"id": "erj_6595a27b5d35015c3ef0c3fd",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"expense_id": "exp_6595a27b5d35015c3ef0c3fd",
"file_metadata_id": "fil_6595a27b5d35015c3ef0c3fd",
"status": "queued",
"attempts": 0,
"max_attempts": 3,
"source_mime_type": "application/pdf",
"source_bytes": 48321,
"source_content_sha256": "f5c4c9c33d9b42e4f130cb593f17741b30e0fb23ac95a6d91d01bf438467a17c",
"simulation_mode": null,
"source_replaced": false,
"expense_updated_at_snapshot": "2026-07-11T08:00:00.000Z",
"queued_at": "2026-07-11T08:00:00.000Z",
"created_at": "2026-07-11T08:00:00.000Z",
"updated_at": "2026-07-11T08:00:00.000Z"
}Get expense by ID
/expenses/{id}Get expense by ID
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier. Prefix depends on the resource, for example inv_, cus_, or ent_.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.get('exp_6595a27b5d35015c3ef0c3fd', {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"id": "exp_6595a27b5d35015c3ef0c3fd",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"supplier_id": "sup_6595a27b5d35015c3ef0c3fd",
"type": "invoice",
"is_draft": false,
"voided_at": null,
"supplier": {
"name": "Orbital Power Systems GmbH",
"address": "Energieweg 8",
"address_2": null,
"post_code": "10115",
"city": "Berlin",
"state": null,
"country": "Germany",
"country_code": "DE",
"tax_number": "DE987654321",
"company_number": "HRB 98765",
"email": "accounts@orbital-power.example",
"phone": "+493012345678",
"peppol_id": "0088:9876543210982",
"is_tax_subject": true
},
"supplier_document_number": "OPS-2025-001",
"date": "2025-10-03",
"date_received": "2025-10-03",
"date_due": "2025-11-02",
"date_service": null,
"date_service_to": null,
"currency_code": "EUR",
"transaction_type": "domestic",
"reference": "DE00-2025-001",
"note": "Ground facility maintenance — March billing period",
"summary_classification": null,
"items": [
{
"name": "Ground facility maintenance",
"description": "Monthly ground facility maintenance",
"quantity": 1,
"unit": "service",
"classification": "service",
"price": 100,
"gross_price": 119,
"discounts": [],
"taxes": [
{
"rate": 19,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100
}
],
"total": 100,
"total_with_tax": 119,
"total_tax": 19
}
],
"taxes": [
{
"rate": 19,
"base": 100,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100,
"reverse_charge": false
}
],
"total": 100,
"total_with_tax": 119,
"total_discount": 0,
"total_paid": 0,
"total_due": 119,
"paid_in_full": false,
"exchange_rate": null,
"attachment_count": 1,
"has_attachment": true,
"metadata": {
"source": "manual"
},
"created_at": "2025-10-03T08:00:00.000Z",
"updated_at": "2025-10-03T08:00:00.000Z"
}Update expense recognition settings
/expenses/recognition/settingsUpdate expense recognition settings
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Body parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.updateRecognitionSettings({
default_method: "service_period_daily"
}, {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"default_method": "service_period_daily"
}Update expense
/expenses/{id}Update expense
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier. Prefix depends on the resource, for example inv_, cus_, or ent_.
Body parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.update('exp_6595a27b5d35015c3ef0c3fd', {
is_draft: false,
supplier_document_number: "OPS-2025-099",
date: "2025-10-12",
date_received: "2025-10-13",
currency_code: "EUR",
summary_classification: "service",
taxes: [
{
rate: 22,
base: 80,
amount: 17.6
}
],
total: 80,
total_with_tax: 97.6
}, {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"id": "exp_6595a27b5d35015c3ef0c3fd",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"supplier_id": "sup_6595a27b5d35015c3ef0c3fd",
"type": "invoice",
"is_draft": false,
"voided_at": null,
"supplier": {
"name": "Orbital Power Systems GmbH",
"address": "Energieweg 8",
"address_2": null,
"post_code": "10115",
"city": "Berlin",
"state": null,
"country": "Germany",
"country_code": "DE",
"tax_number": "DE987654321",
"company_number": "HRB 98765",
"email": "accounts@orbital-power.example",
"phone": "+493012345678",
"peppol_id": "0088:9876543210982",
"is_tax_subject": true
},
"supplier_document_number": "OPS-2025-001",
"date": "2025-10-03",
"date_received": "2025-10-03",
"date_due": "2025-11-02",
"date_service": null,
"date_service_to": null,
"currency_code": "EUR",
"transaction_type": "domestic",
"reference": "DE00-2025-001",
"note": "Ground facility maintenance — March billing period",
"summary_classification": null,
"items": [
{
"name": "Ground facility maintenance",
"description": "Monthly ground facility maintenance",
"quantity": 1,
"unit": "service",
"classification": "service",
"price": 100,
"gross_price": 119,
"discounts": [],
"taxes": [
{
"rate": 19,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100
}
],
"total": 100,
"total_with_tax": 119,
"total_tax": 19
}
],
"taxes": [
{
"rate": 19,
"base": 100,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100,
"reverse_charge": false
}
],
"total": 100,
"total_with_tax": 119,
"total_discount": 0,
"total_paid": 0,
"total_due": 119,
"paid_in_full": false,
"exchange_rate": null,
"attachment_count": 1,
"has_attachment": true,
"metadata": {
"source": "manual"
},
"created_at": "2025-10-03T08:00:00.000Z",
"updated_at": "2025-10-20T00:00:00.000Z"
}Void expense
/expenses/{id}/voidVoids a posted expense and frees its supplier_document_number for reuse by a new expense from the same supplier. A voided expense can be restored unless that number has since been reused by another active expense from the same supplier.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier. Prefix depends on the resource, for example inv_, cus_, or ent_.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.void('exp_6595a27b5d35015c3ef0c3fd', {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"id": "exp_6595a27b5d35015c3ef0c3fd",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"supplier_id": "sup_6595a27b5d35015c3ef0c3fd",
"type": "invoice",
"is_draft": false,
"voided_at": "2025-10-20T12:00:00.000Z",
"supplier": {
"name": "Orbital Power Systems GmbH",
"address": "Energieweg 8",
"address_2": null,
"post_code": "10115",
"city": "Berlin",
"state": null,
"country": "Germany",
"country_code": "DE",
"tax_number": "DE987654321",
"company_number": "HRB 98765",
"email": "accounts@orbital-power.example",
"phone": "+493012345678",
"peppol_id": "0088:9876543210982",
"is_tax_subject": true
},
"supplier_document_number": "OPS-2025-001",
"date": "2025-10-03",
"date_received": "2025-10-03",
"date_due": "2025-11-02",
"date_service": null,
"date_service_to": null,
"currency_code": "EUR",
"transaction_type": "domestic",
"reference": "DE00-2025-001",
"note": "Ground facility maintenance — March billing period",
"summary_classification": null,
"items": [
{
"name": "Ground facility maintenance",
"description": "Monthly ground facility maintenance",
"quantity": 1,
"unit": "service",
"classification": "service",
"price": 100,
"gross_price": 119,
"discounts": [],
"taxes": [
{
"rate": 19,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100
}
],
"total": 100,
"total_with_tax": 119,
"total_tax": 19
}
],
"taxes": [
{
"rate": 19,
"base": 100,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100,
"reverse_charge": false
}
],
"total": 100,
"total_with_tax": 119,
"total_discount": 0,
"total_paid": 0,
"total_due": 119,
"paid_in_full": false,
"exchange_rate": null,
"attachment_count": 1,
"has_attachment": true,
"metadata": {
"source": "manual"
},
"created_at": "2025-10-03T08:00:00.000Z",
"updated_at": "2025-10-03T08:00:00.000Z"
}Disable expense inbound email address
/expenses/inbound-emailRevokes the entity's active inbound email address; mail sent to it afterwards is not accepted. Idempotent: responds 200 even when no address was active. Previously received messages and the expenses created from them are kept. Requires permission to manage entity settings.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
await sdk.expenses.disableExpenseInboundEmail({
entity_id: "YOUR_ENTITY_ID"
});
console.log('Deleted successfully');Returns
{
"available": true,
"enabled": false,
"address": null,
"created_at": null
}Delete expense
/expenses/{id}Deletes an expense together with all of its attachments, including the source file of an OCR recognition. Draft expenses can always be deleted. Posted expenses (including voided ones) can be deleted only when they were entered manually (creation_source=standard) or created by OCR (creation_source=ocr) and did not come from a received e-invoice; expenses created through /expenses/custom, legacy-migrated expenses and expenses from received e-invoices can only be voided (422).
The expense's payments are deleted with it, and each emits a payment.deleted event, exactly like deleting the payment on its own. An expense with credit-note settlements applied to it (or recorded by it) cannot be deleted (422): void it instead. While automatic recognition of the expense's document is still queued or processing, or has finished but its usage is not yet recorded, the request fails with 409 (try again shortly).
Deleting does not change usage: the expense still counts toward the document count of the billing period it was created in, and OCR pages that were scanned stay counted (their usage is kept in the metered usage ledger). Submitting the same document again creates a new expense and a new recognition that is counted again. Stock movements and accounting-recognition entries of the expense are removed.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier. Prefix depends on the resource, for example inv_, cus_, or ent_.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
await sdk.expenses.delete('exp_6595a27b5d35015c3ef0c3fd', {
entity_id: "YOUR_ENTITY_ID"
});
console.log('Deleted successfully');Delete expense attachment
/expenses/{id}/attachments/{fileId}Delete expense attachment
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
await sdk.expenses.deleteExpenseAttachment('exp_6595a27b5d35015c3ef0c3fd', 'FILE_ID', {
entity_id: "YOUR_ENTITY_ID"
});
console.log('Deleted successfully');Retry recognition after a transient failure
/expenses/recognitions/{id}/retryRe-queues a failed recognition job only after an allowed transient provider or source-service error and when attempts remain below max_attempts. Bad or unsupported content should be uploaded as a new expense instead.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Expense recognition job ID
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.retryRecognition("erj_6595a27b5d35015c3ef0c3fd", {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
Recognition job ID
{
"id": "erj_6595a27b5d35015c3ef0c3fd",
"entity_id": "entity-id",
"expense_id": "expense-id",
"file_metadata_id": "file-metadata-id",
"status": "queued",
"provider": "provider",
"model": "model",
"parser_version": "parser-version",
"attempts": 0,
"max_attempts": 0,
"pages_processed": 0,
"page_count": 0,
"warnings": [
{
"code": "missing_required_field",
"field": "field",
"message": "message"
}
],
"provenance": {
"provider": "mistral",
"model": "model",
"parser_version": "parser-version",
"pages_processed": 0,
"doc_size_bytes": 0,
"fields": [
{
"field": "field",
"page": 0,
"confidence": 0,
"source": "annotation",
"note": "note"
}
]
},
"reconciliation": {
"is_reconciled": true,
"expected_total": 0,
"expected_total_with_tax": 0,
"expected_tax": 0,
"reported_total": 0,
"reported_total_with_tax": 0,
"reported_tax": 0,
"differences": [
{
"field": "field",
"expected": 0,
"reported": 0,
"delta": 0
}
]
},
"payment_suggestion": {
"status": "paid",
"amount": 0,
"date": "date",
"method": "method",
"evidence": [
"evidence"
],
"confidence": 0,
"is_partial": true
},
"extracted_draft": {
"type": "invoice",
"supplier": {
"name": "name",
"email": "user@example.com",
"address": "address",
"address_2": "address-2",
"post_code": "post-code",
"city": "city",
"state": "state",
"country": "country",
"country_code": "country-code",
"tax_number": "tax-number",
"company_number": "company-number",
"phone": "phone",
"peppol_id": "peppol-id",
"bank_accounts": [
{
"iban": "iban",
"bic": "bic",
"bank_name": "bank-name",
"account_number": "account-number",
"currency_code": "currency-code"
}
],
"is_tax_subject": true
},
"supplier_document_number": "supplier-document-number",
"date": "date",
"date_received": "date-received",
"date_due": "date-due",
"date_service": "date-service",
"date_service_to": "date-service-to",
"currency_code": "currency-code",
"transaction_type": "domestic",
"reference": "reference",
"note": "note",
"items": [
{
"name": "name",
"description": "description",
"quantity": 0,
"unit": "unit",
"classification": "product",
"price": 0,
"gross_price": 0,
"discounts": [
{
"value": 0,
"type": "percent"
}
],
"taxes": [
{
"rate": 0,
"amount": 0,
"reverse_charge": true,
"is_deductible": true,
"deductible_percentage": 0
}
],
"total": 0,
"total_with_tax": 0,
"total_tax": 0
}
],
"taxes": [
{
"rate": 0,
"base": 0,
"amount": 0,
"reverse_charge": true,
"is_deductible": true,
"deductible_percentage": 0
}
],
"total": 0,
"total_with_tax": 0,
"total_discount": 0,
"summary_classification": "product"
},
"error_code": "error-code",
"error_message": "error-message",
"request_id": "request-id",
"source_filename": "source-filename",
"source_mime_type": "source-mime-type",
"source_bytes": 0,
"source_content_sha256": "source-content-sha256",
"simulation_mode": "sandbox_demo",
"source_replaced": true,
"expense_updated_at_snapshot": "2025-01-15T10:30:00.000Z",
"queued_at": "2025-01-15T10:30:00.000Z",
"started_at": "2025-01-15T10:30:00.000Z",
"completed_at": "2025-01-15T10:30:00.000Z",
"created_at": "2025-01-15T10:30:00.000Z",
"updated_at": "2025-01-15T10:30:00.000Z"
}Get the latest recognition job for an expense
/expenses/{id}/recognitionReturns the latest recognition job linked to the expense, or job: null for manually created expenses. This makes recognition state durable across navigation.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier. Prefix depends on the resource, for example inv_, cus_, or ent_.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.getLatestRecognition('exp_6595a27b5d35015c3ef0c3fd', {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"job": {
"id": "erj_6595a27b5d35015c3ef0c3fd",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"expense_id": "exp_6595a27b5d35015c3ef0c3fd",
"file_metadata_id": "fil_6595a27b5d35015c3ef0c3fd",
"status": "queued",
"attempts": 0,
"max_attempts": 3,
"source_mime_type": "application/pdf",
"source_bytes": 48321,
"source_content_sha256": "f5c4c9c33d9b42e4f130cb593f17741b30e0fb23ac95a6d91d01bf438467a17c",
"simulation_mode": null,
"source_replaced": false,
"expense_updated_at_snapshot": "2026-07-11T08:00:00.000Z",
"queued_at": "2026-07-11T08:00:00.000Z",
"created_at": "2026-07-11T08:00:00.000Z",
"updated_at": "2026-07-11T08:00:00.000Z"
}
}Restore (un-void) an expense
/expenses/{id}/restoreReverses a void, re-activating the expense. Fails with 409 if its supplier_document_number has since been reused by another active expense from the same supplier.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier. Prefix depends on the resource, for example inv_, cus_, or ent_.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.restoreExpense('exp_6595a27b5d35015c3ef0c3fd', {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"id": "exp_6595a27b5d35015c3ef0c3fd",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"supplier_id": "sup_6595a27b5d35015c3ef0c3fd",
"type": "invoice",
"is_draft": false,
"voided_at": null,
"supplier": {
"name": "Orbital Power Systems GmbH",
"address": "Energieweg 8",
"address_2": null,
"post_code": "10115",
"city": "Berlin",
"state": null,
"country": "Germany",
"country_code": "DE",
"tax_number": "DE987654321",
"company_number": "HRB 98765",
"email": "accounts@orbital-power.example",
"phone": "+493012345678",
"peppol_id": "0088:9876543210982",
"is_tax_subject": true
},
"supplier_document_number": "OPS-2025-001",
"date": "2025-10-03",
"date_received": "2025-10-03",
"date_due": "2025-11-02",
"date_service": null,
"date_service_to": null,
"currency_code": "EUR",
"transaction_type": "domestic",
"reference": "DE00-2025-001",
"note": "Ground facility maintenance — March billing period",
"summary_classification": null,
"items": [
{
"name": "Ground facility maintenance",
"description": "Monthly ground facility maintenance",
"quantity": 1,
"unit": "service",
"classification": "service",
"price": 100,
"gross_price": 119,
"discounts": [],
"taxes": [
{
"rate": 19,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100
}
],
"total": 100,
"total_with_tax": 119,
"total_tax": 19
}
],
"taxes": [
{
"rate": 19,
"base": 100,
"amount": 19,
"is_deductible": true,
"deductible_percentage": 100,
"reverse_charge": false
}
],
"total": 100,
"total_with_tax": 119,
"total_discount": 0,
"total_paid": 0,
"total_due": 119,
"paid_in_full": false,
"exchange_rate": null,
"attachment_count": 1,
"has_attachment": true,
"metadata": {
"source": "manual"
},
"created_at": "2025-10-03T08:00:00.000Z",
"updated_at": "2025-10-03T08:00:00.000Z"
}Upload expense attachment
/expenses/{id}/attachmentsUpload expense attachment
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Body parameters
File to upload
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
import fs from 'fs';
const sdk = new SpaceInvoices('YOUR_API_KEY');
// Read file as Buffer
const fileBuffer = fs.readFileSync('/path/to/image.png');
const file = new File([fileBuffer], 'image.png', { type: 'image/png' });
const response = await sdk.expenses.uploadExpenseAttachment('ID', {
file
}, { entity_id: 'YOUR_ENTITY_ID' });
console.log(response);Returns
{
"id": "file_9595a27b5d35015c3ef0c3fa",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"invoice_id": null,
"estimate_id": null,
"credit_note_id": null,
"advance_invoice_id": null,
"delivery_note_id": null,
"expense_id": "exp_6595a27b5d35015c3ef0c3fd",
"category": "attachment",
"url": "https://storage.example.com/si/entities/ent_6595a27b5d35015c3ef0c3fd/attachments/expense.pdf",
"secureUrl": "https://storage.example.com/si/entities/ent_6595a27b5d35015c3ef0c3fd/attachments/expense.pdf",
"publicId": "si/entities/ent_6595a27b5d35015c3ef0c3fd/attachments/expense.pdf",
"secure_url": "https://storage.example.com/si/entities/ent_6595a27b5d35015c3ef0c3fd/attachments/expense.pdf",
"public_id": "si/entities/ent_6595a27b5d35015c3ef0c3fd/attachments/expense.pdf",
"format": "pdf",
"width": null,
"height": null,
"bytes": 245678,
"filename": "supplier-invoice.pdf",
"mime_type": "application/pdf",
"metadata": {},
"created_at": "2025-10-03T08:05:00.000Z",
"updated_at": "2025-10-03T08:05:00.000Z"
}List expense attachments
/expenses/{id}/attachmentsList expense attachments
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Query parameters
Number of results per request.
Default: 10
Opaque cursor to fetch the next page of results. Reuse only with the same effective ordering. Use the value from pagination.next_cursor in the previous response.
Opaque cursor to fetch the previous page of results. Reuse only with the same effective ordering. Use the value from pagination.prev_cursor in the previous response.
Whether to include the total count of items in pagination.total.
Default is true.
When false, pagination.total returns -1 for better performance.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.getExpenseAttachments('exp_6595a27b5d35015c3ef0c3fd', undefined, {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
Pagination metadata including cursors and result counts
{
"data": [
{
"id": "file_9595a27b5d35015c3ef0c3fa",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"invoice_id": null,
"estimate_id": null,
"credit_note_id": null,
"advance_invoice_id": null,
"delivery_note_id": null,
"expense_id": "exp_6595a27b5d35015c3ef0c3fd",
"category": "attachment",
"url": "https://storage.example.com/si/entities/ent_6595a27b5d35015c3ef0c3fd/attachments/expense.pdf",
"secureUrl": "https://storage.example.com/si/entities/ent_6595a27b5d35015c3ef0c3fd/attachments/expense.pdf",
"publicId": "si/entities/ent_6595a27b5d35015c3ef0c3fd/attachments/expense.pdf",
"secure_url": "https://storage.example.com/si/entities/ent_6595a27b5d35015c3ef0c3fd/attachments/expense.pdf",
"public_id": "si/entities/ent_6595a27b5d35015c3ef0c3fd/attachments/expense.pdf",
"format": "pdf",
"width": null,
"height": null,
"bytes": 245678,
"filename": "supplier-invoice.pdf",
"mime_type": "application/pdf",
"metadata": {},
"created_at": "2025-10-03T08:05:00.000Z",
"updated_at": "2025-10-03T08:05:00.000Z"
}
],
"pagination": {
"total": 1,
"next_cursor": null,
"prev_cursor": null,
"has_more": false
}
}List payments affecting an expense
/expenses/{id}/paymentsList payments affecting an expense
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.getExpensePayments('exp_6595a27b5d35015c3ef0c3fd', {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
Pagination metadata including cursors and result counts
{
"data": [
{
"id": "pmt_abc123def456",
"invoice_id": null,
"credit_note_id": null,
"advance_invoice_id": null,
"delivery_note_id": null,
"expense_id": "exp_6595a27b5d35015c3ef0c3fd",
"applied_to_expense_id": null,
"amount": 122,
"amount_converted": 122,
"currency_code": "EUR",
"type": "bank_transfer",
"date": "2025-10-10T00:00:00.000Z",
"reference": "DE00-2025-001",
"tag": null,
"note": "Supplier payment",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"metadata": {},
"deleted_at": null,
"created_at": "2025-10-10T08:00:00.000Z",
"updated_at": "2025-10-10T08:00:00.000Z"
}
],
"pagination": {
"total": 1,
"next_cursor": null,
"prev_cursor": null,
"has_more": false
}
}Create a payment for an expense
/expenses/{id}/paymentsRecord a direct payment against a finalized supplier invoice expense. The payment is capped at the expense's open balance (total_with_tax minus the payments already recorded), compared at the currency's minor unit (0.01 EUR, 1 JPY, 0.001 KWD). A payment that would exceed it returns 422 with cause.code expense_payment_exceeds_open_balance and records nothing. Concurrent payments on one expense are serialized, so they can never together exceed its total.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Body parameters
Payment amount in the linked document currency's major unit; for EUR, 29.90 means €29.90, not 2,990 cents.
Possible values: "cash", "bank_transfer", "card", "check", "paypal", "coupon", "other", "advance"
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.expenses.createExpensePayment('exp_6595a27b5d35015c3ef0c3fd', {
amount: 122,
type: "bank_transfer",
date: "2025-10-10",
reference: "DE00-2025-001",
note: "Supplier payment"
}, {
entity_id: "YOUR_ENTITY_ID"
});
console.log(response);Returns
{
"id": "pmt_abc123def456",
"invoice_id": null,
"credit_note_id": null,
"advance_invoice_id": null,
"delivery_note_id": null,
"expense_id": "exp_6595a27b5d35015c3ef0c3fd",
"applied_to_expense_id": null,
"amount": 122,
"amount_converted": 122,
"currency_code": "EUR",
"type": "bank_transfer",
"date": "2025-10-10T00:00:00.000Z",
"reference": "DE00-2025-001",
"tag": null,
"note": "Supplier payment",
"entity_id": "ent_6595a27b5d35015c3ef0c3fd",
"metadata": {},
"deleted_at": null,
"created_at": "2025-10-10T08:00:00.000Z",
"updated_at": "2025-10-10T08:00:00.000Z"
}