API Documentation

Full reference for the Commissia REST API v1

Introduction

The Commissia REST API provides read-only access to your organization's data: sales reps, deals, commission plans, calculation periods, results and summaries.

The API is available for Growth and Scale plans only. Generate your API keys from Settings > API & Webhooks.
ParameterTypeDescription
Base URLhttps://app.commissia.com/api/v1
Versionv1 (included in the URL)
FormatJSON (application/json)
MethodsGET only (read-only)

Authentication

Every request must include an Authorization header with your API key as a Bearer token.

Keys have the prefix cc_live_ and are displayed only once upon creation. They are stored as SHA-256 hashes.

Example curl
curl -H "Authorization: Bearer cc_live_your_api_key_here" \
  https://app.commissia.com/api/v1/reps

Authentication errors:

CodeDescription
401Missing header, invalid format or revoked key
403Insufficient plan (Growth+ required)

Pagination

All list endpoints support pagination via the limit and offset parameters.

ParameterTypeDescription
limitintegerNumber of results (1-100, default: 50)
offsetintegerOffset from the start (default: 0)
Paginated response
{
  "data": [ ... ],
  "pagination": {
    "total": 42,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

For detail endpoints (/reps/:id, etc.), the response does not include a pagination object:

Single response
{
  "data": { ... }
}

Errors

Errors follow a uniform format:

Error format
{
  "error": {
    "message": "Description of the problem",
    "status": 401
  }
}
HTTP CodeMeaning
200Success
401Unauthenticated (missing, invalid or revoked key)
403Forbidden (insufficient plan)
404Resource not found
429Rate limit exceeded
500Internal server error

Rate Limiting

Each API key is limited to 60 requests per minute (sliding 60-second window). Beyond that, the API returns a 429 code.

429 Response
{
  "error": {
    "message": "Rate limit exceeded",
    "status": 429
  }
}

Wait for the end of the window (60 seconds max) before retrying your requests.

Sales Reps

GET/api/v1/repsList sales reps
GET/api/v1/reps/:idSales rep detail

List parameters:

ParameterTypeDescription
searchstringSearch by last name, first name or email
include_inactivebooleanInclude deleted sales reps (default: false)
limitintegerPagination (1-100, default: 50)
offsetintegerOffset (default: 0)
curl - List sales reps
curl -H "Authorization: Bearer cc_live_xxx" \
  "https://app.commissia.com/api/v1/reps?search=dupont"
Response
{
  "data": [
    {
      "id": "uuid",
      "first_name": "Jean",
      "last_name": "Dupont",
      "email": "jean.dupont@example.com",
      "external_id": null,
      "start_date": "2025-01-01",
      "end_date": null,
      "is_active": true,
      "created_at": "2025-01-15T10:00:00Z",
      "updated_at": "2025-01-15T10:00:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

Deals

GET/api/v1/dealsList deals
GET/api/v1/deals/:idDeal detail

List parameters:

ParameterTypeDescription
searchstringSearch by deal name
rep_iduuidFilter by sales rep
deal_typestringFilter by deal type
close_date_fromdateMin close date (YYYY-MM-DD)
close_date_todateMax close date (YYYY-MM-DD)
limitintegerPagination (1-100, default: 50)
offsetintegerOffset (default: 0)
curl - Deals for a rep over a period
curl -H "Authorization: Bearer cc_live_xxx" \
  "https://app.commissia.com/api/v1/deals?rep_id=uuid&close_date_from=2025-01-01&close_date_to=2025-03-31"
Response
{
  "data": [
    {
      "id": "uuid",
      "deal_name": "Acme Corp - Annual License",
      "deal_type": "New",
      "amount": "15000.00",
      "currency": "EUR",
      "close_date": "2025-02-15",
      "stage": "Won",
      "external_id": null,
      "product_category": "SaaS",
      "rep_id": "uuid",
      "crm_source": null,
      "created_at": "2025-02-10T14:30:00Z",
      "updated_at": "2025-02-10T14:30:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

Commission Plans

GET/api/v1/plansList plans
GET/api/v1/plans/:idPlan detail (with rules)

List parameters:

ParameterTypeDescription
include_inactivebooleanInclude deleted plans (default: false)
limitintegerPagination (1-100, default: 50)
offsetintegerOffset (default: 0)
curl - Plan detail
curl -H "Authorization: Bearer cc_live_xxx" \
  https://app.commissia.com/api/v1/plans/uuid
Response (detail with rules)
{
  "data": {
    "id": "uuid",
    "name": "Sales Plan Q1 2025",
    "description": "Standard sales team plan",
    "effective_from": "2025-01-01",
    "effective_to": "2025-03-31",
    "is_active": true,
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z",
    "rules": [
      {
        "id": "uuid",
        "name": "10% Commission",
        "rule_type": "percentage",
        "priority": 1,
        "conditions": {
          "deal_type": "New",
          "min_amount": "1000",
          "max_amount": null
        },
        "calculation": {
          "rate": "0.10"
        },
        "is_active": true,
        "created_at": "2025-01-01T00:00:00Z",
        "updated_at": "2025-01-01T00:00:00Z"
      }
    ]
  }
}

Calculation Periods

GET/api/v1/periodsList periods
GET/api/v1/periods/:idPeriod detail

List parameters:

ParameterTypeDescription
statusstringFilter by status: draft, calculating, review, approved, paid
limitintegerPagination (1-100, default: 50)
offsetintegerOffset (default: 0)
curl - Approved periods
curl -H "Authorization: Bearer cc_live_xxx" \
  "https://app.commissia.com/api/v1/periods?status=approved"
Response
{
  "data": [
    {
      "id": "uuid",
      "name": "January 2025",
      "period_start": "2025-01-01",
      "period_end": "2025-01-31",
      "status": "approved",
      "calculated_at": "2025-02-01T09:00:00Z",
      "approved_at": "2025-02-03T14:00:00Z",
      "paid_at": null,
      "payment_notes": null,
      "created_at": "2025-01-31T10:00:00Z",
      "updated_at": "2025-02-03T14:00:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

Commission Results

GET/api/v1/periods/:id/resultsDetailed results for a period

Each result represents the commission calculated for a deal according to a specific rule. A deal can generate multiple results if several rules of the same priority apply. Only the highest priority group (lowest number) is used.

Parameters:

ParameterTypeDescription
rep_iduuidFilter by sales rep
limitintegerPagination (1-100, default: 50)
offsetintegerOffset (default: 0)
curl
curl -H "Authorization: Bearer cc_live_xxx" \
  "https://app.commissia.com/api/v1/periods/uuid/results?rep_id=uuid"
Response
{
  "data": [
    {
      "id": "uuid",
      "period_id": "uuid",
      "rep_id": "uuid",
      "deal_id": "uuid",
      "rule_id": "uuid",
      "base_amount": "15000.00",
      "commission_amount": "1500.00",
      "calculation_details": {
        "rule_type": "percentage",
        "rate": "0.10",
        "cap_applied": true,
        "uncapped_amount": "2000.00"
      },
      "adjustment_total": "200.00",
      "created_at": "2025-02-01T09:00:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

The cap_applied and uncapped_amount fields in calculation_details are present when a per-rule cap has been applied. The adjustment_total field is present when manual adjustments exist for this specific result.

Summaries

GET/api/v1/periods/:id/summariesSummaries for a period
GET/api/v1/summariesAll summaries (cross-period)

Summaries aggregate commissions per sales rep per period: number of deals, total revenue and total commission.

Parameters /periods/:id/summaries:

ParameterTypeDescription
rep_iduuidFilter by sales rep
limitintegerPagination (1-100, default: 50)
offsetintegerOffset (default: 0)

Parameters /summaries:

ParameterTypeDescription
period_iduuidFilter by period
rep_iduuidFilter by sales rep
limitintegerPagination (1-100, default: 50)
offsetintegerOffset (default: 0)
curl - Period summaries
curl -H "Authorization: Bearer cc_live_xxx" \
  https://app.commissia.com/api/v1/periods/uuid/summaries
Response
{
  "data": [
    {
      "id": "uuid",
      "period_id": "uuid",
      "rep_id": "uuid",
      "total_deals": 12,
      "total_revenue": "180000.00",
      "total_commission": "18000.00",
      "quota_target": "200000.00",
      "quota_attainment": "0.9000",
      "cap_amount": "20000.00",
      "uncapped_commission": "22000.00",
      "adjustment_total": "500.00",
      "created_at": "2025-02-01T09:00:00Z",
      "updated_at": "2025-02-01T09:00:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

The quota_target and quota_attainment fields are present only when a quota is defined on the plan or overridden for the sales rep. Attainment is expressed as a ratio (1.0 = 100%).

The cap_amount and uncapped_commission fields are present only when a cap is configured. total_commission reflects the amount after the cap is applied.

The adjustment_total field is present when manual adjustments exist for this sales rep during this period. Positive amount = bonus, negative = deduction. Final total = total_commission + adjustment_total.

Webhooks

Outbound webhooks notify your server in real time when an event occurs in Commissia. Configure your endpoints from Settings > API & Webhooks > Webhooks.

Available events:

EventDescription
period.calculatedPeriod calculated
period.approvedPeriod approved
period.paidPeriod paid
deal.createdDeal created
deal.importedDeals imported (CSV or CRM)
rep.createdSales rep created
rep.updatedSales rep updated
rep.deletedSales rep deleted
plan.createdPlan created
plan.updatedPlan updated
plan.deletedPlan deleted
pingConnectivity test

Payload format:

POST request body
{
  "event": "period.approved",
  "data": {
    "id": "uuid",
    "name": "January 2025",
    "status": "approved"
  },
  "timestamp": "2025-02-03T14:00:00.000Z"
}

Headers sent:

HeaderDescription
Content-Typeapplication/json
X-Webhook-SignatureHMAC-SHA256 signature of the body
X-Webhook-EventEvent name
X-Webhook-Delivery-IdUnique delivery identifier

Signature verification:

The X-Webhook-Signature header contains an HMAC-SHA256 of the raw request body, signed with your webhook secret. Verify it to authenticate requests.

Verification in Node.js
import { createHmac, timingSafeEqual } from "crypto";

function verifySignature(body: string, signature: string, secret: string): boolean {
  const expected = createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  return timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your handler:
const rawBody = await request.text();
const signature = request.headers.get("X-Webhook-Signature");

if (!verifySignature(rawBody, signature, WEBHOOK_SECRET)) {
  return new Response("Invalid signature", { status: 401 });
}

const payload = JSON.parse(rawBody);

Retry policy:

If your endpoint responds with a non-2xx code or does not respond within 10 seconds, Commissia automatically retries:

AttemptDelay
2nd attempt30 seconds
3rd attempt2 minutes

After 3 failed attempts, the delivery is marked as failed. View delivery history in the Deliveries tab of the API & Webhooks page.