The evSuryam API lets you read and write the same data your team works with in the dashboard — customers, quotations, invoices, and inventory — from your own code. It is a conventional, versioned REST API: predictable resource URLs, JSON request and response bodies, bearer-token authentication, and standard HTTP status codes. This page is the orientation map; deep-dive guides like sending invoice events to your accounting system build on it.
Overview & base URL
Every request goes to a single, version-pinned base URL. The version lives in the path so a future v2 never breaks code written against v1.
Base URL: https://api.evsuryam.com/v1
- All requests must be made over HTTPS. Plain-HTTP requests are rejected, not redirected.
- Request and response bodies are JSON. Send
Content-Type: application/jsonon writes andAccept: application/jsonon every call. - Responses wrap a single record under
dataand paginated collections underdatawithlinksandmetaalongside. - Identifiers are opaque ULID strings (for example
01HF8Z9Q...) — never assume they are sequential integers. - Money is returned as strings (
"124000.00") to avoid floating-point rounding, and timestamps are ISO-8601 with an offset.
public/images/docs/api-integrations.pngOne workspace, one tenantEvery token is scoped to the company that created it. The API only ever returns data for your own workspace — there is no cross-tenant access, and you never pass a company id in requests.
Authentication
The API authenticates with personal access tokens sent as a bearer token in the Authorization header. Generate a token under Settings → API → Tokens:
- Open Settings → API → Tokens and click Generate token.
- Give it a descriptive name (for example
tally-sync-prod) so you can revoke the right one later. - Choose abilities — scope the token to only what it needs, such as
invoices:readorinventory:write. - Copy the token immediately. It is shown once and stored only as a hash — if you lose it, revoke and regenerate.
Send it on every request:
curl https://api.evsuryam.com/v1/customers \
-H "Authorization: Bearer evs_live_9f3c7a1e8b24d6f0a5c1e2b3d4f5a6b7" \
-H "Accept: application/json"
Treat tokens like passwordsNever commit a token to source control, embed it in a browser app, or log it. Store it in a secrets manager or server environment variable. Revoke any token the moment it may have leaked — revocation is instant.
A missing or invalid token returns 401 Unauthenticated. A valid token that lacks the ability for an endpoint returns 403 Forbidden.
Rate limits & errors
Requests are rate-limited per token. The default ceiling is 120 requests per minute; bulk and sync endpoints carry their own lower limits. Every response includes the current budget in headers:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window. |
X-RateLimit-Remaining | Requests left before you are throttled. |
Retry-After | Seconds to wait, sent only on a 429 response. |
When you exceed the limit you receive 429 Too Many Requests. Back off for the number of seconds in Retry-After before retrying. Errors share one envelope across the whole API:
{
"message": "The given data was invalid.",
"code": "VALIDATION_FAILED",
"errors": {
"email": ["The email field is required."]
}
}
Match on the stable code string, not on the human-readable message. Common codes: UNAUTHENTICATED (401), FORBIDDEN (403), NOT_FOUND (404), VALIDATION_FAILED (422), and TOO_MANY_REQUESTS (429).
Core resources
The four resources below mirror the heart of the dashboard. Each supports the standard list / read / create / update verbs unless noted.
| Resource | Endpoint | What it represents |
|---|---|---|
| Customers | /v1/customers | Homeowners and businesses you sell to, including site address and GSTIN. |
| Quotations | /v1/quotations | Priced proposals with line items, taxes, and validity. |
| Invoices | /v1/invoices | GST-compliant tax invoices with full CGST/SGST/IGST breakdown. |
| Inventory | /v1/inventory/items | Stock of panels, inverters, and BOS, with on-hand quantities. |
Standard verbs follow REST conventions:
| Verb | Path | Action | Success code |
|---|---|---|---|
| GET | /v1/invoices | List invoices (paginated) | 200 |
| GET | /v1/invoices/{id} | Retrieve one invoice | 200 |
| POST | /v1/invoices | Create an invoice | 201 |
| PATCH | /v1/invoices/{id} | Update an invoice | 200 |
| GET | /v1/customers | List customers | 200 |
| POST | /v1/customers | Create a customer | 201 |
List endpoints accept ?page and ?per_page (capped at 100), filters such as ?status=paid, sorting with ?sort=-issued_at (leading - for descending), and eager-loading with ?include=customer,line_items.
Example: listing invoices
Fetch the most recent paid invoices, newest first:
curl "https://api.evsuryam.com/v1/invoices?status=paid&sort=-issued_at&per_page=2" \
-H "Authorization: Bearer evs_live_9f3c7a1e8b24d6f0a5c1e2b3d4f5a6b7" \
-H "Accept: application/json"
A successful response (200 OK):
{
"data": [
{
"id": "01HF8Z9Q4M2P0T7VBC3K1XR8AD",
"number": "INV-2026-0184",
"status": "paid",
"issued_at": "2026-06-09T11:20:04+05:30",
"customer": {
"id": "01HF8Z6Y7N0E5R2QABV9MK3T1C",
"name": "Anjali Desai",
"gstin": null
},
"total": "248000.00",
"gst_breakdown": {
"taxable_value": "221428.57",
"cgst": "13285.71",
"sgst": "13285.72",
"igst": "0.00"
}
},
{
"id": "01HF8Y2A0B9C8D7E6F5G4H3J2K",
"number": "INV-2026-0183",
"status": "paid",
"issued_at": "2026-06-08T16:45:51+05:30",
"customer": {
"id": "01HF8Y0Z1Y2X3W4V5U6T7S8R9Q",
"name": "Sunrise Textiles Pvt Ltd",
"gstin": "24AABCS1429B1Z6"
},
"total": "1062000.00",
"gst_breakdown": {
"taxable_value": "948214.29",
"cgst": "0.00",
"sgst": "0.00",
"igst": "113785.71"
}
}
],
"links": {
"first": "https://api.evsuryam.com/v1/invoices?page=1",
"prev": null,
"next": "https://api.evsuryam.com/v1/invoices?page=2",
"last": "https://api.evsuryam.com/v1/invoices?page=46"
},
"meta": {
"current_page": 1,
"per_page": 2,
"last_page": 46,
"total": 91
}
}
Notice the second invoice carries igst (an inter-state sale to a registered GSTIN) while the first uses cgst + sgst (intra-state). evSuryam computes the split for you — see GST & compliance for the rules.
Webhook subscriptions
Polling the API for changes is wasteful. Instead, subscribe to webhooks and evSuryam will POST a JSON event to your endpoint the instant something happens — no cron job, no missed updates.
Create a subscription under Settings → API → Webhooks: enter the HTTPS URL that will receive events and tick the event types you care about. The most-used events:
| Event | Fires when |
|---|---|
invoice.paid | An invoice is fully settled — push it to your ledger. |
invoice.created | A new invoice is issued. |
installation.stage_completed | An install pipeline stage (survey, mounting, commissioning) is marked done. |
inventory.low_stock | An item drops below its reorder threshold. |
Every delivery is signed with an HMAC in the X-evSuryam-Signature header so you can verify it genuinely came from evSuryam, and each carries a unique event id for idempotency. The dedicated guide walks through the full payload, signature verification, and retry behaviour:
Sending invoice events to your accounting system →
Tally & Zoho Books sync
Most Indian solar vendors keep their books in Tally or Zoho Books. evSuryam pushes sales and purchase ledgers into both so your accountant never re-keys an invoice.
- Tally: export ready-to-import XML vouchers for sales and purchase ledgers, or run the lightweight connector that posts vouchers to Tally's ODBC/XML gateway on your LAN. Ledger names and GST classifications map automatically from your catalog's HSN/SAC codes.
- Zoho Books: a direct API push creates the matching invoice and bill records in your Zoho organisation, including line items, tax rates, and the customer/vendor contact. Authorise once via OAuth under Settings → API → Accounting.
Sync can run on a schedule (nightly) or be triggered in real time off the invoice.paid webhook. Reverse-charge purchases — common on imported inverters — are tagged so the RCM liability lands in the right ledger; see reverse-charge on imported inverters.
Start with exportsIf you are not ready to wire up live API sync, the pre-built Tally XML and Zoho CSV exports under Settings → API → Accounting get you 90% of the value with zero code — download, import, done.
Next steps
You now have the lay of the land: base URL, tokens, resources, webhooks, and accounting sync. The natural next step is wiring real-time invoice events into your ledger — start with the focused invoice events guide. If you are still setting up your workspace, the getting started guide covers the prerequisites.