Developers

Connect your software to Polisync

Read and write your customers, policies, renewals and claims from your own systems, and get a signed webhook the moment something changes. Use it for a website enquiry form, a CRM or spreadsheet sync, accounting, or WhatsApp and email automation.

Included in the Enterprise plan

API keys and webhooks are available to workspaces on the Enterprise plan. These docs are open to everyone. See pricing or write to hello@polisync.in.

Quick start

The base URL is https://app.polisync.in/api/public/v1. Everything is JSON over HTTPS.

1. Create a key. In Polisync, open Settings, Developers and choose Create API key. Give it only the permissions the integration needs. The key is shown once, so copy it into your server's secret store.

2. Check the connection.

curl -X GET "https://app.polisync.in/api/public/v1/me" \
  -H "Authorization: Bearer $POLISYNC_API_KEY"

3. Add a customer. You confirm their DPDP consent with consentGiven. Sending an Idempotency-Key makes the request safe to retry.

curl -X POST "https://app.polisync.in/api/public/v1/customers" \
  -H "Authorization: Bearer $POLISYNC_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-123" \
  -d '{
  "name": "Ramesh Patel",
  "type": "individual",
  "phone": "+919876543210",
  "email": "ramesh.patel@gmail.com",
  "dateOfBirth": "1985-03-14",
  "city": "Surat",
  "state": "Gujarat",
  "agencyId": "cmv1a2b3c0002xyzagency",
  "consentGiven": true
}'

4. Read them back. For example, active policies expiring before the end of the year:

curl -X GET "https://app.polisync.in/api/public/v1/policies?status=active&expiryTo=2026-12-31" \
  -H "Authorization: Bearer $POLISYNC_API_KEY"

Next, see the API reference, or set up webhooks to be told about changes instead of polling.

Authentication

Send your key in the Authorization header on every request:

Authorization: Bearer psk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

A key belongs to one workspace, so every request only ever sees that workspace's data. Each key carries scopes: the permissions you tick when you create it. A request outside its scopes gets 403 forbidden. A key can never have more power than the person who created it.

ScopeAllows
customer:readList and fetch customers.
customer:panCustomers are returned with PAN masked unless this is on. Needs Read customers.
customer:createAdd customers. You confirm their DPDP consent.
customer:updateEdit existing customers.
policy:readList and fetch policies.
policy:createAdd policies. Renewals are created automatically.
policy:updateEdit policies, including status and expiry.
claim:readList and fetch claims and their timeline.
claim:createReport claims against policies.
claim:updateChange status, dates and amounts, and add notes.
renewal:readList renewals and their status.
agency:readList and fetch agencies.

Keep keys on your server

Anyone holding a key can use it. Never put one in a website, a mobile app or a public repository. Browser calls are not allowed (the API sends no CORS headers). Give each integration its own key, set an expiry, and revoke a key the moment you doubt it. Revoking works on the very next request.

Requests and responses

  • Send and receive JSON. Use Content-Type: application/json on writes. Request bodies are limited to 1 MB.
  • Unknown fields in a request body are rejected, so a typo never silently does nothing.
  • Dates are YYYY-MM-DD. Timestamps are ISO 8601 in UTC. Money is a number in rupees. Phone numbers are Indian mobile numbers in +91 format.
  • Enum values keep their stored form, such as half_yearly and non_corporate.
  • On PATCH, send only the fields to change. Send null to clear an optional field.
  • Every response carries an X-Request-Id. Quote it if you contact support.

A successful response always looks like this:

Single record
{
  "success": true,
  "data": {
    "id": "cmv1a2b3c0001xyzcustomer",
    "...": "..."
  }
}
List
{
  "success": true,
  "data": [
    {
      "id": "..."
    }
  ],
  "pagination": {
    "total": 134,
    "page": 1,
    "limit": 20,
    "totalPages": 7
  }
}

Pagination, filtering and sync

Lists take page (from 1) and limit (1 to 100, default 20), and return a pagination block. Results are in a stable order, so paging does not repeat or skip records. Each list documents its own filters in the reference.

To keep another system in step, store the time of your last sync and ask for what changed since: ?updatedSince=2026-10-26T00:00:00Z. Every list supports it. Or use webhooks and skip polling.

Rate limits

Each key may make 60 requests a minute. Every response shows where you stand:

HeaderMeaning
X-RateLimit-LimitRequests allowed per minute.
X-RateLimit-RemainingRequests left in this minute.
X-RateLimit-ResetUnix time when the window resets.
Retry-AfterOn a 429 only: seconds to wait before trying again.

When you get 429, wait for Retry-After and retry. For bulk work, slow down and use limit=100. Repeated failed authentication from one address is also throttled.

Errors

Every failure has the same shape, and a stable machine code:

{
  "success": false,
  "error": "One or more fields are invalid.",
  "code": "validation_error",
  "details": [
    {
      "field": "phone",
      "message": "Invalid Indian mobile number"
    }
  ]
}

Match on code, not on the message text, which may be reworded. details names each field that failed.

HTTPcodeMeaning
400invalid_jsonThe request body is not valid JSON.
401unauthorizedThe API key is missing, invalid, expired or revoked.
403forbiddenThe key does not have the scope this endpoint needs.
403plan_requiredThe workspace's plan does not include API access (Enterprise).
403account_suspendedThe workspace is suspended.
404not_foundThe record does not exist in your workspace.
409conflictThe request clashes with existing data, such as a duplicate policy number.
409idempotency_conflictThat Idempotency-Key was already used with a different request.
409idempotency_in_progressA request with that Idempotency-Key is still running. Retry shortly.
413payload_too_largeThe request body is over 1 MB.
422validation_errorA field is missing or invalid. The details array names each one.
403plan_limit_reachedYour plan's limit for customers or policies is full.
429rate_limitedToo many requests. Wait for the number of seconds in the Retry-After header.
500server_errorSomething went wrong on our side. Retry; if it persists, contact support.

Retry 429 and 5xx responses with a growing delay. Do not retry 4xx responses unchanged: fix the request first.

Idempotency

A network failure can leave you not knowing whether a create worked. Send an Idempotency-Key header (a unique value you choose, up to 255 characters) on POST requests. Polisync stores the first successful response for 24 hours:

  • The same key with the same request returns the original response again, with Idempotent-Replayed: true, and creates nothing new.
  • The same key with a different request returns 409 idempotency_conflict.
  • A request that failed is not stored, so you can correct it and resend with the same key.
curl -X POST "https://app.polisync.in/api/public/v1/customers" \
  -H "Authorization: Bearer $POLISYNC_API_KEY" \
  -H "Idempotency-Key: enquiry-form-8421" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

Data protection

Customer records are personal data, and claims and policies can include health information. You are responsible for it under India's DPDP Act 2023, and Polisync is built to help:

  • Creating a customer needs consentGiven: true, and the consent is logged with the key and the caller's IP address.
  • PAN numbers are masked (ABCDE****F) unless the key has the explicit full-PAN scope, and always in webhooks.
  • Send data only to systems you control, over HTTPS, and keep only what you need.
  • Delete a customer in Polisync and webhook subscribers are told, so mirrors can remove their copy too.

Read our Privacy Policy and Terms of Service.

Versioning

The version is in the URL (/api/public/v1). Within v1 we only add things: new endpoints, new optional fields, new response fields and new webhook event types. So write your code to ignore fields it does not know. A change that could break your code would ship as v2, with notice and an overlap period. See the changelog.

A machine-readable description is at /developers/openapi.json (OpenAPI 3.1). Import it into Postman, Insomnia or a code generator.