Developer Guides
Everything you need to start building on the ERPLY REST API v1.
Introduction
The ERPLY API is a RESTful JSON API covering sales, purchasing, inventory, accounting, HR, POS and more. Every endpoint is documented in the interactive reference, generated from the same OpenAPI specification the SDKs are built against.
Two official SDKs wrap the API with full type definitions:
| SDK | Package | Install |
|---|---|---|
| JavaScript / TypeScript | erply-js | npm i erply-js |
| Python (sync + async) | erply-python | pip install erply-python |
Authentication
All requests are authenticated with an API key, created under Settings โ API Keys in the admin panel. Pass it as a Bearer token:
Authorization: Bearer erp_sk_your_key_here
Accept: application/json
Content-Type: application/json
invoices:read, invoices:write).
A request to an endpoint your key lacks permission for returns 403 with the required
permission in the body. Keys are tenant-scoped โ they only ever see their own company's data.
cURL example
curl -H "Authorization: Bearer erp_sk_..." \
-H "Accept: application/json" \
https://erply.app/api/v1/customers?per_page=25
Base URL & versioning
All v1 endpoints are served under:
https://erply.app/api/v1/
The version is part of the path (/api/v1), so future breaking changes ship under a new prefix.
Responses & pagination
Single-resource responses share a consistent envelope:
{
"success": true,
"message": "OK",
"data": { "id": 1, "name": "Acme Co", ... }
}
List endpoints are paginated, returning meta and links:
{
"success": true,
"data": [ ... ],
"meta": { "current_page": 1, "per_page": 25, "total": 120, "last_page": 5 },
"links": { "first": "...", "last": "...", "prev": null, "next": "...?page=2" }
}
Control paging with ?page= and ?per_page= query parameters.
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
403 | Key lacks the required permission |
404 | Resource not found (or not in your tenant) |
422 | Validation failed โ see errors object |
429 | Rate limit exceeded |
{
"success": false,
"message": "The given data was invalid.",
"errors": { "email": ["The email field is required."] }
}
JavaScript / TypeScript SDK erply-js
Install
npm install erply-js
# or: pnpm add erply-js / yarn add erply-js
Quickstart
import { ErplyClient } from 'erply-js';
const erply = new ErplyClient({
apiKey: process.env.ERPLY_API_KEY!, // 'erp_sk_...'
baseUrl: 'https://erply.app', // your ERP instance
});
// List customers (paginated)
const customers = await erply.customers.list({ per_page: 25 });
console.log(customers.data, customers.meta.total);
// Create an invoice
const { data: invoice } = await erply.invoices.create({
customer_id: 1,
issue_date: '2026-06-01',
due_date: '2026-06-30',
lines: [{ description: 'Consulting', quantity: 1, unit_price: 5000 }],
});
// Post it to the ledger
await erply.invoices.post(invoice.id);
Available resources
erply.customers, erply.invoices, erply.products, erply.journalEntries โ each with list, get, create, update, delete (plus post / creditNote on invoices). All inputs and responses are fully typed.
Python SDK erply-python
Install
pip install erply-python
Quickstart (synchronous)
from erply import ErplyClient, CreateInvoiceInput, InvoiceLine
with ErplyClient(api_key="erp_sk_...", base_url="https://erply.app") as erply:
# List customers
customers = erply.customers.list(per_page=50)
for c in customers.data:
print(c.name)
# Create + post an invoice
res = erply.invoices.create(CreateInvoiceInput(
customer_id=1,
issue_date="2026-06-01",
due_date="2026-06-30",
lines=[InvoiceLine(description="Consulting", quantity=1, unit_price=5000)],
))
erply.invoices.post_invoice(res.data.id)
Async
import asyncio
from erply import AsyncErplyClient
async def main():
async with AsyncErplyClient(api_key="erp_sk_...", base_url="https://erply.app") as erply:
products = await erply.products.list(per_page=100)
print(products.meta.total)
asyncio.run(main())
ErplyApiError for 4xx/5xx responses (with .status and
.message) and ErplyNetworkError for transport failures.