Expiro home
Developers

API Documentation

A small, read-only REST API for your contracts. Everything is scoped to your account.

Base URL

https://expiro.io/api/v1

Authentication

The API uses bearer tokens. In Expiro, an account admin creates a token under Settings → API . The full token is shown once on creation, so copy it then.

Send it in the Authorization header on every request:

curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://expiro.io/api/v1/contracts

A token can be given an expiry (30, 90 or 365 days, or never) and revoked at any time. A revoked or expired token stops working immediately.

Tokens are read-only by default. When creating a token you can tick write access to also allow creating contracts (the POST /contracts endpoint below). Reading is always allowed.

Rate limit

Each account may make 60 requests per minute. Over that, the API returns 429 Too Many Requests; wait a moment and retry.

List contracts

GET /api/v1/contracts returns every contract on your account.

curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://expiro.io/api/v1/contracts

Response:

{
  "data": [
    {
      "id": "5f9b2c1a-8e3d-4a7b-9c10-2b6e1f0a4d22",
      "name": "Annual retainer",
      "client_name": "Acme Corp",
      "client_email": "ops@acme.com",
      "value": "24000.00",
      "currency": "GBP",
      "start_date": "2026-01-01",
      "end_date": "2026-12-31",
      "status": "active",
      "pipeline_status": "upcoming",
      "auto_renewal": false,
      "renewal_notice_days": 90,
      "custom_fields": { "po_number": "PO-1188" },
      "inserted_at": "2026-01-02T09:14:00.000000Z",
      "updated_at": "2026-03-10T11:00:00.000000Z"
    }
  ]
}

Contracts expiring soon

GET /api/v1/contracts/expiring returns active contracts ending within a window, newest first - handy as a trigger. Pass ?days=N (1 to 365, default 30). Each record adds a days_until_expiry field.

curl -H "Authorization: Bearer YOUR_TOKEN" \
  "https://expiro.io/api/v1/contracts/expiring?days=60"

Create a contract

POST /api/v1/contracts creates a contract. Requires a token with write access.

curl -X POST -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Annual retainer","client_name":"Acme Corp","value":"24000","currency":"GBP","end_date":"2026-12-31"}' \
  https://expiro.io/api/v1/contracts

Returns 201 Created with the new contract. A token without write access returns 403; a plan over its contract limit returns 403; invalid fields return 422 with an errors object.

Verify a token

GET /api/v1/me returns the account behind the token. Useful for confirming a connection works.

curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://expiro.io/api/v1/me

Get one contract

GET /api/v1/contracts/:id returns a single contract by its id.

curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://expiro.io/api/v1/contracts/5f9b2c1a-8e3d-4a7b-9c10-2b6e1f0a4d22

Response:

{
  "data": {
    "id": "5f9b2c1a-8e3d-4a7b-9c10-2b6e1f0a4d22",
    "name": "Annual retainer",
    "client_name": "Acme Corp",
    "status": "active",
    "end_date": "2026-12-31"
  }
}

An id that does not belong to your account returns 404 Not Found.

Errors

Errors come back as JSON with an error message:

{ "error": "Invalid or missing API token." }
Status Meaning
401 The token is missing, invalid, expired or revoked.
403 The token lacks write access, or your plan is over its contract limit.
404 No contract with that id on your account.
422 The contract could not be created; see the errors object.
429 Rate limit exceeded (60 requests per minute). Retry shortly.
5xx Something went wrong on our side. Retry later.

Need a token? Head to Settings → API in your account. Questions? Email support@expiro.io.