ERPLY Developer Guides
Home API Reference Changelog Swagger UI Log in

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:

SDKPackageInstall
JavaScript / TypeScripterply-jsnpm i erply-js
Python (sync + async)erply-pythonpip 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
Each key carries a scoped permission set (e.g. 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

StatusMeaning
401Missing or invalid API key
403Key lacks the required permission
404Resource not found (or not in your tenant)
422Validation failed โ€” see errors object
429Rate 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())
Both clients raise ErplyApiError for 4xx/5xx responses (with .status and .message) and ErplyNetworkError for transport failures.

Next steps