API ReferenceAPI Documentation
API Reference

API Documentation

Complete REST API reference with authentication, endpoints, and code examples

20 min read

Authentication Required

All API requests require authentication. Include your API key in the request header as shown below. You can generate API keys from your Account Settings.

Authentication

Authenticate API requests by including your API key in the Authorization header. All requests must be made over HTTPS.

Authentication Header
Bash
# Include the API key in every request
curl -X GET https://api.umbraerp.com/v1/invoices \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json"

If authentication fails, the API returns a 401 Unauthorized response:

401 Unauthorized Response
JSON
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or expired API key",
"status": 401
}
}

Base URL

All API endpoints are relative to the following base URL:

Base URL
Bash
https://api.umbraerp.com/v1

Endpoints Overview

The API is organized around REST principles. Below is a summary of the main resource endpoints:

MethodEndpointDescription
GET/invoicesList all invoices
POST/invoicesCreate a new invoice
GET/customersList all customers
POST/customersCreate a new customer
GET/productsList all products
POST/productsCreate a new product
GET/employeesList all employees
GET/reports/profit-lossGenerate profit & loss report
GET/webhooksList webhook subscriptions

List Invoices

Retrieve a paginated list of all invoices in your account. Supports filtering, sorting, and pagination through query parameters.

GET /invoices
Bash
curl -X GET "https://api.umbraerp.com/v1/invoices?page=1&limit=20&status=unpaid&sort=due_date:asc" \
-H "Authorization: Bearer YOUR_API_KEY"

Successful response:

200 OK Response
JSON
{
"data": [
{
"id": "inv_abc123",
"number": "INV-01001",
"customer": {
"id": "cust_xyz789",
"name": "Acme Corp"
},
"total": 1500.00,
"currency": "USD",
"status": "unpaid",
"due_date": "2026-04-15",
"created_at": "2026-03-01T10:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"total_pages": 1
}
}

Create an Invoice

Create a new invoice by sending a POST request with the required fields in the request body:

POST /invoices
Bash
curl -X POST https://api.umbraerp.com/v1/invoices \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cust_xyz789",
"items": [
{
"description": "Web Development Services",
"quantity": 40,
"unit_price": 75.00
},
{
"description": "Hosting (Monthly)",
"quantity": 1,
"unit_price": 49.99
}
],
"due_date": "2026-04-15",
"currency": "USD",
"notes": "Payment due within 30 days"
}'

Successful creation returns the invoice with a 201 status:

201 Created Response
JSON
{
"data": {
"id": "inv_def456",
"number": "INV-01002",
"customer_id": "cust_xyz789",
"items": [
{
"description": "Web Development Services",
"quantity": 40,
"unit_price": 75.00,
"total": 3000.00
},
{
"description": "Hosting (Monthly)",
"quantity": 1,
"unit_price": 49.99,
"total": 49.99
}
],
"subtotal": 3049.99,
"tax": 0,
"total": 3049.99,
"currency": "USD",
"status": "draft",
"due_date": "2026-04-15",
"created_at": "2026-03-04T12:00:00Z"
}
}

Error Handling

The API uses standard HTTP status codes to indicate success or failure. Error responses include a structured JSON body with details:

Error Response Format
JSON
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request body contains invalid fields",
"status": 422,
"details": [
{
"field": "customer_id",
"message": "Customer ID is required"
}
]
}
}

Common Status Codes

CodeMeaning
200Request succeeded
201Resource created successfully
400Bad request (malformed syntax)
401Unauthorized (invalid API key)
403Forbidden (insufficient permissions)
404Resource not found
422Validation error
429Rate limit exceeded
500Internal server error

Rate Limiting

API requests are rate limited based on your plan tier. Rate limit information is included in the response headers:

Rate Limit Headers
Bash
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1705312800
Retry-After: 60

Handling Rate Limits

Implement exponential backoff in your client code to gracefully handle rate limit responses. Check the Retry-After header to determine how long to wait before retrying the request.

SDK Examples

Use the official SDK for a simpler integration experience:

TypeScript SDK Example
TypeScript
import { UmbraClient } from '@umbra-erp/sdk';
const client = new UmbraClient({
apiKey: process.env.UMBRA_API_KEY,
});
// List invoices
const invoices = await client.invoices.list({
page: 1,
limit: 20,
status: 'unpaid',
});
// Create an invoice
const newInvoice = await client.invoices.create({
customer_id: 'cust_xyz789',
items: [
{ description: 'Consulting', quantity: 10, unit_price: 150 },
],
due_date: '2026-04-15',
});
// List customers
const customers = await client.customers.list({ limit: 50 });
// Create a product
const product = await client.products.create({
name: 'Widget Pro',
sku: 'WDG-PRO-001',
price: 29.99,
stock: 500,
});
console.log('Unpaid invoices:', invoices.data.length);
console.log('New invoice:', newInvoice.data.number);
Python SDK Example
Python
from umbra_erp import UmbraClient
client = UmbraClient(api_key="YOUR_API_KEY")
# List invoices
invoices = client.invoices.list(page=1, limit=20, status="unpaid")
# Create an invoice
new_invoice = client.invoices.create(
customer_id="cust_xyz789",
items=[
{"description": "Consulting", "quantity": 10, "unit_price": 150},
],
due_date="2026-04-15",
)
# List customers
customers = client.customers.list(limit=50)
# Create a product
product = client.products.create(
name="Widget Pro",
sku="WDG-PRO-001",
price=29.99,
stock=500,
)
print(f"Unpaid invoices: {invoices.pagination.total}")
print(f"New invoice: {new_invoice.data.number}")