// API reference
Tapat.link REST API
Every document in Tapat.link is available over a secure, predictable REST API. Use it to connect stores, banks, logistics providers and your own apps.
https://<company>.tapat.link/apiAuthentication
Authenticate every request with an API key and secret, generated per user under Settings → API access. Requests run with that user's permissions, so create a dedicated integration user with only the roles it needs.
curl "https://acme.tapat.link/api/method/ping" \ -H "Authorization: token $API_KEY:$API_SECRET"Keep your API secret on the server. Never embed it in a browser or mobile app.
Resources
Each document type is a resource. Standard endpoints follow the same pattern for every resource:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/resource/{doctype} | List records |
| GET | /api/resource/{doctype}/{name} | Get one record |
| POST | /api/resource/{doctype} | Create a record |
| PUT | /api/resource/{doctype}/{name} | Update a record |
| DELETE | /api/resource/{doctype}/{name} | Delete a draft record |
curl "https://acme.tapat.link/api/resource/Sales%20Invoice/INV-2026-01842" \ -H "Authorization: token $API_KEY:$API_SECRET"curl -X POST "https://acme.tapat.link/api/resource/Customer" \ -H "Authorization: token $API_KEY:$API_SECRET" \ -H "Content-Type: application/json" \ -d '{ "customer_name": "Gulf Fresh Foods", "tax_id": "300987654300003" }'curl -X PUT "https://acme.tapat.link/api/resource/Customer/Gulf%20Fresh%20Foods" \ -H "Authorization: token $API_KEY:$API_SECRET" \ -H "Content-Type: application/json" \ -d '{ "credit_limit": 250000 }'curl -X DELETE "https://acme.tapat.link/api/resource/Item/SAMPLE-ITEM" \ -H "Authorization: token $API_KEY:$API_SECRET"Filtering & pagination
List endpoints accept fields, filters, order_by, limit_start and limit_page_length parameters. Filters are JSON arrays of [field, operator, value].
# List the 20 most recent unpaid invoicescurl -G "https://acme.tapat.link/api/resource/Sales%20Invoice" \ -H "Authorization: token $API_KEY:$API_SECRET" \ --data-urlencode 'fields=["name","customer","grand_total","status"]' \ --data-urlencode 'filters=[["status","=","Unpaid"]]' \ --data-urlencode 'order_by=posting_date desc' \ --data-urlencode 'limit_page_length=20'- Operators: =, !=, >, <, >=, <=, like, in, not in, between
- Default page size is 20; the maximum is 500
- Use limit_start to page through results
Webhooks
Subscribe to events under Settings → Webhooks. Tapat.link sends a signed POST request to your URL whenever an event occurs, and retries with exponential backoff for up to 24 hours.
{ "event": "sales_invoice.cleared", "created_at": "2026-09-28T10:42:17+03:00", "data": { "name": "INV-2026-01842", "customer": "Riyadh Build Supplies", "grand_total": 44160.0, "zatca_status": "CLEARED" }}Verify the X-Signature header, an HMAC-SHA256 of the raw body using your webhook secret, before trusting a payload.
Rate limits
Requests are limited per API key. Every response includes X-RateLimit-Limit and X-RateLimit-Remaining headers.
| Plan | Requests per minute |
|---|---|
| Starter | 60 (read-only) |
| Business | 300 |
| Enterprise | Custom |
Errors
Errors use standard HTTP status codes and a consistent JSON body.
{ "error": { "status": 422, "code": "validation_error", "message": "Customer tax ID must be 15 digits", "field": "tax_id" }}| Status | Meaning |
|---|---|
| 400 | Malformed request |
| 401 | Missing or invalid credentials |
| 403 | The user lacks permission for this action |
| 404 | Record not found |
| 422 | Validation failed |
| 429 | Rate limit exceeded |