Independence Day offer · ₹52/employee/moClaim offer
INDPayroll
API reference

Platform

Health, tokens, key introspection, organizations and webhook subscriptions.

Base URLhttps://api.indpayroll.com/v17 endpoints
GET /healthNo auth

Liveness probe

Unauthenticated. Answers 200 while the engine is accepting calls. Use it for uptime monitoring, not for checking your own credentials - GET /me does that.

Responses

  • 200 The engine is up. HealthStatus
Request
curl -X GET https://api.indpayroll.com/v1/health \
  -H "Authorization: Bearer $INDP_API_KEY"
Response · 200
{
  "status": "ok",
  "version": "2026.09.1",
  "time": "2026-09-30T09:15:04Z"
}
POST /auth/tokenNo auth

Exchange a key pair for a short-lived token

Optional. Sign every request with HMAC if your security review requires it; otherwise exchange the key pair once here and send the returned token as a bearer token for the next 60 minutes. Tokens carry the same scopes as the key, or a subset if you ask for one.

Body application/json · required

key_id required
string
The public half of your key pair.
key_secret required
string (password)
The secret half. Never send this from a browser.
scopes
string[]
Narrow the token to a subset of the key's own scopes. Defaults to all of them.

Responses

  • 200 A token usable as Authorization: Bearer. TokenResponse
  • 400 The request was malformed or failed validation. ErrorResponse
  • 401 The key is missing, unknown, or the HMAC signature did not verify. ErrorResponse
  • 429 Rate limit exceeded. Retry after the number of seconds in Retry-After. ErrorResponse
Request
curl -X POST https://api.indpayroll.com/v1/auth/token \
  -H "Authorization: Bearer $INDP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "key_id": "indp_live_9f2c41ab",
  "key_secret": "sk_live_0a7f...redacted",
  "scopes": [
    "payroll:read",
    "payroll:write"
  ]
}'
Response · 200
{
  "access_token": "indp_tok_01J9K7YR4H...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scopes": [
    "payroll:read",
    "payroll:write"
  ]
}
GET /me

Describe the calling key

Returns the company the key belongs to, the organizations it can reach, its scopes and its rate limits. Call it once at start-up: it is the cheapest way to confirm credentials and to learn which organization_ids you may pass.

Responses

  • 200 Key context. Me
  • 401 The key is missing, unknown, or the HMAC signature did not verify. ErrorResponse
  • 429 Rate limit exceeded. Retry after the number of seconds in Retry-After. ErrorResponse
Request
curl -X GET https://api.indpayroll.com/v1/me \
  -H "Authorization: Bearer $INDP_API_KEY"
Response · 200
{
  "key_id": "indp_live_9f2c41ab",
  "name": "Acme HRIS production",
  "mode": "live",
  "company": {
    "id": 17,
    "name": "Acme Technologies Private Limited"
  },
  "scopes": [
    "org:read",
    "employees:write",
    "payroll:write",
    "statutory:read"
  ],
  "organization_ids": [
    42,
    43
  ],
  "rate_limits": {
    "requests_per_minute": 600,
    "payroll_runs_per_hour": 60,
    "burst": 60
  },
  "api_version": "2026-09-01"
}
GET /organizations

List organizations

Every payroll entity this key can act on, parents and children alike.

Query parameters

page
integer
1-based page number.
per_page
integer
Items per page. The engine caps this at 200.

Responses

  • 200 Organizations. object
  • 401 The key is missing, unknown, or the HMAC signature did not verify. ErrorResponse
  • 429 Rate limit exceeded. Retry after the number of seconds in Retry-After. ErrorResponse
POST /organizations

Create a child organization

For multi-entity payroll: a second entity with its own PF code, ESI code, PT state and pay calendar, under the same company. Payroll settings are not inherited - configure the new entity before its first run.

Headers

Idempotency-Key
string
A unique key, at most 255 characters, that makes this request safe to retry. Replaying a key within 24 hours returns the original response and does not act again.

Body application/json · required

name required
string
legal_name
string
parent_id
integer
Omit to hang the entity off the key's own company.
pan
string
tan
string
gstin
string
pf_code
string
esi_code
string
pt_state
string
lwf_state
string
address
Address
pay_calendar
PayCalendar
When the month closes and when people are paid.

Responses

  • 201 Created. Organization
  • 400 The request was malformed or failed validation. ErrorResponse
  • 401 The key is missing, unknown, or the HMAC signature did not verify. ErrorResponse
  • 403 The key is valid but lacks the scope, or cannot reach this organization. ErrorResponse
  • 429 Rate limit exceeded. Retry after the number of seconds in Retry-After. ErrorResponse
Request
curl -X POST https://api.indpayroll.com/v1/organizations \
  -H "Authorization: Bearer $INDP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Manufacturing LLP",
  "pan": "AABCA9876B",
  "tan": "BBNA54321C",
  "pf_code": "MHTHA0099887000",
  "esi_code": "31000998870000999",
  "pt_state": "Maharashtra",
  "address": {
    "line1": "Plot 21, MIDC Phase II",
    "city": "Pune",
    "state": "Maharashtra",
    "pincode": "411019"
  },
  "pay_calendar": {
    "cycle": "monthly",
    "cut_off_day": 25,
    "salary_from_day": 1,
    "salary_to_day": 31,
    "pay_day": 7
  }
}'
GET /organizations/{id}

Retrieve an organization

The entity profile the engine reads for statutory output - name, GSTIN, PAN, TAN, PF and ESI codes, PT state, address and pay calendar.

Path parameters

id required
string
INDPayroll id of the resource.

Responses

  • 200 The organization. Organization
  • 401 The key is missing, unknown, or the HMAC signature did not verify. ErrorResponse
  • 403 The key is valid but lacks the scope, or cannot reach this organization. ErrorResponse
  • 404 No such resource, or it belongs to an organization this key cannot reach. ErrorResponse
Request
curl -X GET https://api.indpayroll.com/v1/organizations/{id} \
  -H "Authorization: Bearer $INDP_API_KEY"
Response · 200
{
  "id": 42,
  "parent_id": null,
  "name": "Acme Technologies Private Limited",
  "gstin": "21AABCA1234A1Z5",
  "pan": "AABCA1234A",
  "tan": "BBNA12345F",
  "pf_code": "ODBBN0012345000",
  "esi_code": "44000123450000999",
  "pt_state": "Odisha",
  "lwf_state": "Odisha",
  "address": {
    "line1": "4th Floor, Fortune Towers",
    "city": "Bhubaneswar",
    "state": "Odisha",
    "pincode": "751023",
    "country": "India"
  },
  "pay_calendar": {
    "cycle": "monthly",
    "cut_off_day": 25,
    "salary_from_day": 1,
    "salary_to_day": 31,
    "pay_day": 5
  },
  "currency": "INR",
  "employee_count": 86
}
PUT /organizations/{id}

Update statutory IDs and the pay calendar

Replaces the fields you send. Changing the pay calendar takes effect from the next period the engine opens; runs already calculated are untouched.

Path parameters

id required
string
INDPayroll id of the resource.

Headers

Idempotency-Key
string
A unique key, at most 255 characters, that makes this request safe to retry. Replaying a key within 24 hours returns the original response and does not act again.

Body application/json · required

name
string
legal_name
string
gstin
string
tan
string
pan
string
pf_code
string
esi_code
string
pt_state
string
lwf_state
string
address
Address
pay_calendar
PayCalendar
When the month closes and when people are paid.

Responses

  • 200 Updated. Organization
  • 400 The request was malformed or failed validation. ErrorResponse
  • 401 The key is missing, unknown, or the HMAC signature did not verify. ErrorResponse
  • 403 The key is valid but lacks the scope, or cannot reach this organization. ErrorResponse
  • 404 No such resource, or it belongs to an organization this key cannot reach. ErrorResponse
Request
curl -X PUT https://api.indpayroll.com/v1/organizations/{id} \
  -H "Authorization: Bearer $INDP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "lwf_state": "Odisha",
  "pay_calendar": {
    "cycle": "monthly",
    "cut_off_day": 27,
    "salary_from_day": 1,
    "salary_to_day": 31,
    "pay_day": 5
  }
}'