Start free trial
14 days free trial - no credit card needed
Hisab
Pricing
Sales: +212 649 22 43 64
Start free trial

14 days free trial - no credit card needed

Login

API reference

The Hisab REST API

Authenticate with an API key, create and finalize invoices, manage customers and recurring schedules. Every endpoint below is live in production.

31endpoints|https://hisab.ma/api/v1

Getting started

The Hisab API is a JSON REST API served over HTTPS. Every request is authenticated with an API key and scoped to your organization.

Base URL
https://hisab.ma/api/v1
API access is included in the Professional and Fiduciaire plans. Compare plans

Rate limits

Requests are limited per minute and per API key. Past the limit the API returns 429 RATE_LIMIT_EXCEEDED with a Retry-After header.

PlanRequestsAPI keys
Professional120 req/min10
Fiduciaire300 req/minUnlimited

Every response reports your current usage in these headers:

headers
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 119
X-RateLimit-Reset: 1780750800

Authentication

API keys are created from the dashboard: Settings, then API keys. You choose the scopes when creating the key, and the full secret is shown only once.

Send the key as a Bearer token in the Authorization header:

cURL
curl https://hisab.ma/api/v1/invoices \
  -H "Authorization: Bearer hisab_live_***"
hisab_live_***

Production key. Acts on your real data.

hisab_test_***

Test key. Same format, for staging integrations.

Keys are stored hashed (SHA-256) on our side and can be revoked at any time from the dashboard. A 401 means the key is missing, invalid or revoked:

401
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or missing API key"
  }
}

Scopes

Each key carries an explicit list of scopes. A request that needs a scope the key does not have returns 403 FORBIDDEN, with the required scopes in the error details.

invoices:readinvoices:writeinvoices:finalizeinvoices:sendinvoices:paymentinvoices:voidinvoices:exportrecurring:readrecurring:writerecurring:deletecustomers:readcustomers:writecustomers:deleteorganization:readorganization:writewebhooks:readwebhooks:writeorganizations:readorganizations:writeorganizations:archive

When creating a key, the dashboard offers three bundles (read only, invoicing, full access), and you can always pick scopes individually.

Pagination

List endpoints accept page and per_page (max 100) and return the pagination block inside meta:

JSON
{
  "success": true,
  "data": [ ... ],
  "meta": {
    "pagination": { "total": 128, "page": 1, "perPage": 20, "totalPages": 7 }
  }
}

Errors

All errors share one shape: success is false, and error carries a stable code, a human-readable message and optional field-level details. The standard codes:

VALIDATION_ERROR400
INVALID_JSON400
UNAUTHORIZED401
FORBIDDEN403
API_DISABLED403
SUBSCRIPTION_EXPIRED403
API_TIER_NOT_SUPPORTED403
ORG_HEADER_REQUIRED400
ACCOUNT_KEY_REQUIRED403
ENTITY_CAP_REACHED403
NOT_FOUND404
RATE_LIMIT_EXCEEDED429
INTERNAL_ERROR500

Webhooks

Hisab signs and POSTs an event to your endpoint whenever an invoice or a customer changes. Webhooks are configured from the dashboard: Settings, then Webhooks.

invoice.createdinvoice.updatedinvoice.finalizedinvoice.sentinvoice.paidinvoice.voidedcustomer.createdcustomer.updatedcustomer.deleted
Read the webhooks guide

Invoices

Create draft invoices, finalize them to assign the official number, then track sending, payment and voiding. Finalized invoices export as PDF and UBL 2.1 XML.

GET/api/v1/invoices

List invoices

Returns your organization's invoices, newest first. Filter by status, customer or issue date.

Scopesinvoices:read
Query parameters
pageintegerdefault: 1
per_pageintegerdefault: 20 (max 100)
orderstringdefault: desc
ascdesc
statusstring
draftfinalizedsentpaidvoid
customer_iduuid
date_fromdate (YYYY-MM-DD)
date_todate (YYYY-MM-DD)
cURL
curl https://hisab.ma/api/v1/invoices \
  -H "Authorization: Bearer hisab_live_***"
GET/api/v1/invoices/:id

Get an invoice

Returns a single invoice with its customer, line items and totals.

Scopesinvoices:read
cURL
curl https://hisab.ma/api/v1/invoices/{id} \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/invoices

Create an invoice

Creates a draft. Totals and taxes are computed server-side from the line items.

Scopesinvoices:writeinvoice.created
Body parameters
customer_idrequireduuid
issue_daterequireddate (YYYY-MM-DD)
due_datedate (YYYY-MM-DD)
currencystringdefault: MAD
payment_termsstring
notesstring
internal_notesstring
items[].descriptionrequiredstring
items[].quantityrequirednumber
items[].unit_pricerequirednumber
items[].tax_ratenumberdefault: 20
cURL
curl https://hisab.ma/api/v1/invoices \
  -X POST \
  -H "Authorization: Bearer hisab_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cus_2b81fe",
    "issue_date": "2026-06-05",
    "items": [
      {
        "description": "Integration services",
        "quantity": 8,
        "unit_price": 1300,
        "tax_rate": 20
      }
    ]
  }'
PATCH/api/v1/invoices/:id

Update an invoice

Updates a draft. Finalized invoices are immutable; the call returns INVOICE_NOT_EDITABLE.

Scopesinvoices:writeinvoice.updated
Body parameters
customer_iduuid
issue_datedate (YYYY-MM-DD)
due_datedate (YYYY-MM-DD)
currencystring
payment_termsstring
notesstring
items[].descriptionstring
items[].quantitynumber
items[].unit_pricenumber
items[].tax_ratenumberdefault: 20
Specific errorsINVOICE_NOT_EDITABLE
cURL
curl https://hisab.ma/api/v1/invoices/{id} \
  -X PATCH \
  -H "Authorization: Bearer hisab_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "due_date": "2026-08-05"
  }'
POST/api/v1/invoices/:id/finalize

Finalize an invoice

Assigns the official sequential number and locks the invoice. This is the legal issuance step.

Scopesinvoices:finalizeinvoice.finalized
Specific errorsINVOICE_NOT_DRAFTVALIDATION_ERROR
cURL
curl https://hisab.ma/api/v1/invoices/{id}/finalize \
  -X POST \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/invoices/:id/send

Mark as sent

Records that the finalized invoice was delivered to the customer.

Scopesinvoices:writeinvoice.sent
Specific errorsINVALID_STATUS_TRANSITION
cURL
curl https://hisab.ma/api/v1/invoices/{id}/send \
  -X POST \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/invoices/:id/pay

Mark as paid

Records a payment, with an optional method and reference.

Scopesinvoices:writeinvoice.paid
Body parameters
paid_atdatetime (ISO 8601)
payment_methodstring
payment_referencestring
Specific errorsINVALID_STATUS_TRANSITION
cURL
curl https://hisab.ma/api/v1/invoices/{id}/pay \
  -X POST \
  -H "Authorization: Bearer hisab_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_method": "bank_transfer",
    "payment_reference": "VIR-20260605"
  }'
POST/api/v1/invoices/:id/void

Void an invoice

Cancels a finalized invoice with a mandatory reason. Paid invoices cannot be voided.

Scopesinvoices:writeinvoice.voided
Body parameters
reasonrequiredstring
Specific errorsCANNOT_VOID_PAIDALREADY_VOIDED
cURL
curl https://hisab.ma/api/v1/invoices/{id}/void \
  -X POST \
  -H "Authorization: Bearer hisab_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Duplicate billing"
  }'
GET/api/v1/invoices/:id/pdf

Download the PDF

Returns the validated PDF in French, English or Arabic. Available once finalized.

Scopesinvoices:export
Query parameters
localestringdefault: fr
frenar
Specific errorsPDF_NOT_AVAILABLE
cURL
curl https://hisab.ma/api/v1/invoices/{id}/pdf \
  -H "Authorization: Bearer hisab_live_***"
GET/api/v1/invoices/:id/xml

Download the XML

Returns the UBL 2.1 XML of the finalized invoice.

Scopesinvoices:export
Specific errorsXML_NOT_AVAILABLE
cURL
curl https://hisab.ma/api/v1/invoices/{id}/xml \
  -H "Authorization: Bearer hisab_live_***"

Customers

B2B and B2C customers with Moroccan identifiers (ICE, RC). Archiving preserves the invoice history.

GET/api/v1/customers

List customers

Returns customers, with search across name, email and ICE.

Scopescustomers:read
Query parameters
pageintegerdefault: 1
per_pageintegerdefault: 20 (max 100)
orderstringdefault: desc
ascdesc
searchstring
typestring
b2bb2c
statusstring
activeinactivearchived
cURL
curl https://hisab.ma/api/v1/customers \
  -H "Authorization: Bearer hisab_live_***"
GET/api/v1/customers/:id

Get a customer

Returns a single customer with contact details and address.

Scopescustomers:read
cURL
curl https://hisab.ma/api/v1/customers/{id} \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/customers

Create a customer

B2B customers should carry their 15-digit ICE. Duplicate ICEs are rejected within your organization.

Scopescustomers:writecustomer.created
Body parameters
namerequiredstring
typerequiredstring
b2bb2c
icestring (15 digits)
legal_namestring
rcstring
emailstring
phonestring
address.streetstring
address.citystring
address.postal_codestring
address.countrystringdefault: MA
notesstring
tagsstring[]
cURL
curl https://hisab.ma/api/v1/customers \
  -X POST \
  -H "Authorization: Bearer hisab_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MERIT Sarl",
    "type": "b2b",
    "ice": "001234567000089",
    "email": "compta@example.ma"
  }'
PATCH/api/v1/customers/:id

Update a customer

Partial update: send only the fields that change.

Scopescustomers:writecustomer.updated
Body parameters
namestring
typestring
b2bb2c
icestring (15 digits)
emailstring
phonestring
addressobject
notesstring
tagsstring[]
statusstring
activeinactivearchived
cURL
curl https://hisab.ma/api/v1/customers/{id} \
  -X PATCH \
  -H "Authorization: Bearer hisab_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "finance@example.ma"
  }'
DELETE/api/v1/customers/:id

Archive a customer

Soft delete. The customer is archived and their invoice history stays intact.

Scopescustomers:deletecustomer.deleted
Specific errorsALREADY_ARCHIVED
cURL
curl https://hisab.ma/api/v1/customers/{id} \
  -X DELETE \
  -H "Authorization: Bearer hisab_live_***"

Recurring invoices

Schedules that generate invoices automatically, weekly to yearly, with optional auto-finalize and auto-send.

GET/api/v1/recurring-invoices

List schedules

Returns recurring invoice schedules. Filter by status, customer or frequency.

Scopesinvoices:read
Query parameters
pageintegerdefault: 1
per_pageintegerdefault: 20 (max 100)
orderstringdefault: desc
ascdesc
statusstring
activepausedcompletedcancelled
customer_iduuid
frequencystring
weeklybiweeklymonthlyquarterlybiannuallyyearly
searchstring
cURL
curl https://hisab.ma/api/v1/recurring-invoices \
  -H "Authorization: Bearer hisab_live_***"
GET/api/v1/recurring-invoices/:id

Get a schedule

Returns a schedule with its latest generation history.

Scopesinvoices:read
cURL
curl https://hisab.ma/api/v1/recurring-invoices/{id} \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/recurring-invoices

Create a schedule

Defines the frequency, start date and line items of the future invoices.

Scopesinvoices:write
Body parameters
customer_idrequireduuid
frequencyrequiredstring
weeklybiweeklymonthlyquarterlybiannuallyyearly
start_daterequireddate (YYYY-MM-DD)
namestring
interval_countinteger (1-12)default: 1
day_of_monthinteger (1-28)
day_of_weekinteger (0-6)
end_datedate (YYYY-MM-DD)
max_occurrencesinteger
auto_finalizebooleandefault: false
auto_sendbooleandefault: false
days_until_dueinteger (0-365)default: 30
currencystringdefault: MAD
items[].descriptionrequiredstring
items[].quantityrequirednumber
items[].unit_pricerequirednumber
items[].tax_ratenumberdefault: 20
Specific errorsQUOTA_EXCEEDED
cURL
curl https://hisab.ma/api/v1/recurring-invoices \
  -X POST \
  -H "Authorization: Bearer hisab_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cus_2b81fe",
    "frequency": "monthly",
    "start_date": "2026-07-01",
    "auto_finalize": true,
    "items": [
      {
        "description": "Monthly retainer",
        "quantity": 1,
        "unit_price": 10400,
        "tax_rate": 20
      }
    ]
  }'
PUT/api/v1/recurring-invoices/:id

Update a schedule

Adjusts an active or paused schedule. Completed and cancelled schedules are read-only.

Scopesinvoices:write
Body parameters
frequencystring
weeklybiweeklymonthlyquarterlybiannuallyyearly
end_datedate (YYYY-MM-DD)
auto_finalizeboolean
auto_sendboolean
days_until_dueinteger (0-365)
itemsarray
Specific errorsINVALID_STATE
cURL
curl https://hisab.ma/api/v1/recurring-invoices/{id} \
  -X PUT \
  -H "Authorization: Bearer hisab_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "auto_send": true
  }'
DELETE/api/v1/recurring-invoices/:id

Delete a schedule

Removes the schedule and its history. Already generated invoices are not affected.

Scopesinvoices:write
cURL
curl https://hisab.ma/api/v1/recurring-invoices/{id} \
  -X DELETE \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/recurring-invoices/:id/generate

Generate now

Creates the next invoice immediately, honoring auto-finalize and auto-send.

Scopesinvoices:write
Body parameters
issue_datedate (YYYY-MM-DD)default: today
Specific errorsINVALID_STATECUSTOMER_INACTIVE
cURL
curl https://hisab.ma/api/v1/recurring-invoices/{id}/generate \
  -X POST \
  -H "Authorization: Bearer hisab_live_***"
GET/api/v1/recurring-invoices/:id/history

Generation history

Lists past runs with their generated invoice numbers and status.

Scopesinvoices:read
Query parameters
limitintegerdefault: 20 (max 100)
cURL
curl https://hisab.ma/api/v1/recurring-invoices/{id}/history \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/recurring-invoices/:id/pause

Pause a schedule

Stops future generation until the schedule is resumed.

Scopesinvoices:write
Specific errorsINVALID_STATE
cURL
curl https://hisab.ma/api/v1/recurring-invoices/{id}/pause \
  -X POST \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/recurring-invoices/:id/resume

Resume a schedule

Restarts a paused schedule, optionally from a new next run date.

Scopesinvoices:write
Body parameters
next_run_datedate (YYYY-MM-DD)
Specific errorsINVALID_STATE
cURL
curl https://hisab.ma/api/v1/recurring-invoices/{id}/resume \
  -X POST \
  -H "Authorization: Bearer hisab_live_***"

Organization

Your organization profile, subscription state and API quotas.

GET/api/v1/organization

Get the organization

Returns legal identifiers, contact info, subscription and API quotas.

Scopesorganization:read
cURL
curl https://hisab.ma/api/v1/organization \
  -H "Authorization: Bearer hisab_live_***"
PATCH/api/v1/organization

Update the organization

Updates legal identifiers, contact info and the billing address.

Scopesorganization:write
Body parameters
legal_namestring
icestring
rcstring
if_numberstring
vat_numberstring
phonestring
emailstring
websitestring (URL)
billing_addressobject
cURL
curl https://hisab.ma/api/v1/organization \
  -X PATCH \
  -H "Authorization: Bearer hisab_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+212 5 22 00 00 01"
  }'

apiDocsPage.nav.organizations

Organization management for multi-entity integrations. These endpoints require an ACCOUNT-level key (hisab_acct_). After provisioning, operate any entity on the regular endpoints by sending the X-Organization-Id header with the same account key. An ICE already registered on the platform cannot be used again, even by another account - it identifies exactly one legal entity.

GET/api/v1/organizations

List your organizations

Returns every organization the key's owner owns. Archived entities are excluded unless include_archived=true.

Scopesorganizations:read
Query parameters
include_archivedbooleandefault: false
Specific errorsACCOUNT_KEY_REQUIRED
cURL
curl https://hisab.ma/api/v1/organizations \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/organizations

Create an organization

Provisions a new legal entity under your account. Your plan's entity cap applies; contact support to raise it.

Scopesorganizations:write
Body parameters
legal_namerequiredstring
icestring (15 digits)
rcstring
if_numberstring
phonestring
emailstring
address_streetstring
address_citystring
address_postal_codestring
Specific errorsACCOUNT_KEY_REQUIREDENTITY_CAP_REACHED
cURL
curl https://hisab.ma/api/v1/organizations \
  -X POST \
  -H "Authorization: Bearer hisab_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "legal_name": "Filiale Casablanca SARL",
    "ice": "002345678000071"
  }'
GET/api/v1/organizations/{id}

Get an organization

Returns one owned organization. Unknown or foreign ids return 404.

Scopesorganizations:read
Specific errorsACCOUNT_KEY_REQUIRED
cURL
curl https://hisab.ma/api/v1/organizations/{id} \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/organizations/{id}/archive

Archive an organization

Soft-archives the entity: it is frozen everywhere (API, dashboard, crons) but nothing is deleted. Fully reversible.

Scopesorganizations:archive
Specific errorsACCOUNT_KEY_REQUIREDALREADY_ARCHIVED
cURL
curl https://hisab.ma/api/v1/organizations/{id}/archive \
  -X POST \
  -H "Authorization: Bearer hisab_live_***"
POST/api/v1/organizations/{id}/restore

Restore an organization

Reverses an archive; the entity resumes normal operation immediately.

Scopesorganizations:archive
Specific errorsACCOUNT_KEY_REQUIREDNOT_ARCHIVED
cURL
curl https://hisab.ma/api/v1/organizations/{id}/restore \
  -X POST \
  -H "Authorization: Bearer hisab_live_***"