Complyance Logo

ISV credit management APIs

⚠️ Internal sandbox preview — not approved for partner or production use. Credit reads and writes do not yet share one environment model (see Environment below). Do not integrate against production credit data until Complyance confirms the environment contract.

Use the Connect V3 credit APIs to inspect an ISV credit pool, manage company allowances, submit bulk changes, and reconcile activity through the immutable credit ledger.

An allowance is a commercial limit for a company. Creating or changing an allowance does not transfer, reserve, or consume credits from the ISV pool. Credits are consumed only by approved Complyance workflows.

Endpoints

OperationMethodEndpoint
List allowancesGET/v3/connect/credits/allowances
Read one company's credit stateGET/v3/connect/credits/allowances/{companyId}
Pause active allowancePOST/v3/connect/credits/allowances/{companyId}/pause
Create or replace scheduled allowancePUT/v3/connect/credits/allowances/{companyId}/scheduled
Submit bulk changesPOST/v3/connect/credits/allowances/bulk
Read ledgerGET/v3/connect/credits/transactions
Read ISV poolGET/v3/connect/credits/pool
Resume active allowancePOST/v3/connect/credits/allowances/{companyId}/resume
Read bulk jobGET/v3/connect/credits/allowances/bulk/{jobId}
Create or replace active allowancePUT/v3/connect/credits/allowances/{companyId}/current
Cancel scheduled allowanceDELETE/v3/connect/credits/allowances/{companyId}/scheduled
Read ledger export statusGET/v3/connect/credits/exports/{exportId}
Request ledger exportPOST/v3/connect/credits/exports

There is no public debit, refund, reversal, reservation, finalization, or credit-purchase endpoint.

In the examples, replace {BASE_URL}, {API_KEY}, and the other brace-delimited placeholders with your values. {BASE_URL} is https://prod.gets.complyance.io for the deployed platform, or http://localhost:3003 for local development. All example IDs, timestamps, limits, balances, and usage values are illustrative.

Authentication

Send the ISV workspace API key in the X-API-Key header:

X-API-Key: {API_KEY}

An API key may alternatively be sent as a Bearer token:

Authorization: Bearer {API_KEY}

Keep API keys secret. Never include a real API key in documentation, browser code, logs, or source control.

Credit endpoints are scoped to the workspace associated with the credential.

Environment

Environment behaviour currently differs between reads and writes:

  • Writes — pause, resume, scheduled create/replace/cancel, current create/replace, and bulk jobs — read the X-Environment header and store the result against that data environment. Accepted values are sandbox, test, and development (all resolve to sandbox data), and production and prod (production data). Any other value returns 400 CONNECT_INVALID_ENVIRONMENT.
  • When X-Environment is omitted on a write, it defaults to production. Always send the header explicitly on every write, and use sandbox unless production credit management has been confirmed with Complyance.
  • Reads — pool, allowance list, single-company state, ledger, and exports — do not accept an environment and are not environment-filtered. A read may therefore not reflect the environment a write targeted.

Because of this asymmetry, these APIs are an internal sandbox preview and are not approved for partner or production use. This section will be updated when reads and writes share one environment model.

Common headers

HeaderRequiredDescription
X-API-KeyYesAPI key for an eligible ISV partner workspace. Use this or Authorization, not both.
X-EnvironmentFor writesData environment for allowance writes and bulk jobs: sandbox or production. Omitted defaults to production — always set it explicitly. Read endpoints ignore this header.
AcceptNoSet to application/json.
Content-TypeFor requests with a bodySet to application/json.
Idempotency-KeyFor writes and export requestsUnique key identifying the intended operation. Reusing the key with the same payload returns the original result.
If-None-MatchFor first allowance creationUse * when no current or scheduled resource exists.
If-MatchFor updates and state changesQuoted resource version, for example "3".
X-Correlation-IdNoIdentifier used to correlate direct allowance writes and bulk jobs with your system. It is ignored on reads and export requests.

Access

  • Workspace API keys can read and write credit resources for their own ISV workspace.
  • Authenticated Owners, Admins, and Partners can perform allowance writes.
  • Other authenticated workspace members have read-only access.
  • Every companyId must be the canonical 24-character hexadecimal company ID and must belong to the authenticated ISV workspace.
  • Internal onboarding and workspace identifiers are not accepted as public company references.
  • Allowance writes and allowance-list results are limited to active managed companies. The single-company state, ledger, and export endpoints can read historical data for an inactive company.

Response envelope

Successful responses use this envelope:

{
  "success": true,
  "data": {},
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

After authentication succeeds, Connect validation and service errors use this envelope:

{
  "success": false,
  "error": {
    "code": "CONNECT_ALLOWANCE_WRITE_PRECONDITION_FAILED",
    "message": "Unable to complete allowance write."
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

Use meta.requestId when contacting support.

Authentication can fail before the Connect route handles the request. Missing, invalid, or revoked credentials can therefore return a plain-text 401 Unauthorized response instead of the JSON error envelope. Check the HTTP status and Content-Type before parsing an error body as JSON.

Allowance lifecycle

A company can have one current allowance and at most one scheduled allowance.

StatusMeaning
scheduledFuture allowance waiting for its startAt.
activeCurrent allowance permits consumption while capacity remains.
pausedNew consumption is blocked without changing the period dates.
expiredThe allowance period has ended.
supersededA scheduled allowance activated and replaced the prior current allowance.

Allowance periods use an inclusive startAt and an exclusive endAt. Send UTC ISO 8601 timestamps, such as 2030-01-01T00:00:00.000Z. periodType is classification metadata; it does not calculate dates or renew an allowance automatically.

Replacing a current allowance keeps its existing allowancePeriodId, startAt, finalized usage, and active reservations. The new limit cannot be lower than finalized usage plus active reservations.

Concurrency and idempotency

Every allowance write requires an Idempotency-Key and a resource precondition:

  • To create a resource, send If-None-Match: *.
  • To replace a resource, send If-Match: "{version}" using the latest version.
  • To pause, resume, or cancel, send If-Match: "{version}".
  • Read the latest versions from the response body and ETag headers.

Do not send If-None-Match and If-Match together. Reusing an idempotency key with a different payload returns a conflict.

Resource schemas

Allowance

{
  "limit": 1000,
  "periodType": "monthly",
  "planReference": "plan-pro-2026",
  "metadata": {
    "subscriptionId": "sub_123"
  },
  "allowancePeriodId": "period_01",
  "startAt": "2026-08-01T00:00:00.000Z",
  "endAt": "2026-09-01T00:00:00.000Z",
  "status": "active",
  "version": 3,
  "finalizedUsage": 250,
  "reserved": 20,
  "updatedAt": "2026-08-12T10:00:00.000Z"
}

Company credit state

{
  "companyId": "{COMPANY_ID}",
  "current": {},
  "scheduled": null,
  "usage": 250,
  "reserved": 20,
  "available": 730,
  "effectiveAvailability": 730,
  "blockReason": null,
  "warnings": [],
  "asOf": "2026-08-12T10:00:00.000Z",
  "lastChangedAt": "2026-08-12T09:00:00.000Z"
}

current and scheduled contain an Allowance object or null.

Warning values

WarningMeaning
COMPANY_THRESHOLD_REACHEDFinalized usage plus reservations reached at least 80% of the current allowance.
OVER_ALLOCATIONTotal current and scheduled allowances exceed the available ISV pool. The write still succeeds.
EFFECTIVE_AVAILABILITY_LIMITED_BY_POOLThe ISV pool is lower than the remaining company allowance.
POOL_LOWAvailable pool credits reached the low threshold.
POOL_CRITICALAvailable pool credits reached the critical threshold.
POOL_EXHAUSTEDNo pool credits are available.

Block reasons

Block reasonMeaning
NO_ACTIVE_ALLOWANCEThe company has no current active allowance.
ALLOWANCE_PAUSEDThe current allowance is paused.
ALLOWANCE_INACTIVEThe current allowance is not active.
ALLOWANCE_EXHAUSTEDFinalized usage plus reservations exhausted the company allowance.
POOL_EXHAUSTEDThe ISV pool is exhausted.

1. List allowances

Returns a cursor-paginated snapshot of active managed companies' credit states.

GET /v3/connect/credits/allowances

Query parameters

ParameterTypeRequiredDescription
cursorstringNoOpaque cursor returned by the preceding page.
limitintegerNoNumber of results from 1 to 100. Defaults to 25.
companyIdstringNoReturn one managed company.
statusstringNoFilter by current or scheduled allowance status.
countryCodestringNoFilter companies by country.
blockReasonstringNoFilter by block reason.
effectiveFromdate-timeNoInclude allowances overlapping the period beginning at this time.
effectiveTodate-timeNoInclude allowances overlapping the period ending at this time. Must be later than effectiveFrom.

Inactive and archived companies are omitted, including when companyId is supplied. Use Read one company's credit state to inspect retained credit history for an inactive company.

Request

curl --get '{BASE_URL}/v3/connect/credits/allowances' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json' \
  --data-urlencode 'countryCode=AE' \
  --data-urlencode 'limit=25'

Response

200 OK

{
  "success": true,
  "data": {
    "items": [
      {
        "companyId": "{COMPANY_ID}",
        "current": {
          "limit": 1000,
          "periodType": "monthly",
          "allowancePeriodId": "period_01",
          "startAt": "2026-08-01T00:00:00.000Z",
          "endAt": "2026-09-01T00:00:00.000Z",
          "status": "active",
          "version": 3,
          "finalizedUsage": 250,
          "reserved": 20
        },
        "scheduled": null,
        "usage": 250,
        "reserved": 20,
        "available": 730,
        "effectiveAvailability": 730,
        "blockReason": null,
        "warnings": [],
        "asOf": "2026-08-12T10:00:00.000Z",
        "lastChangedAt": "2026-08-12T09:00:00.000Z"
      }
    ],
    "nextCursor": null,
    "asOf": "2026-08-12T10:00:00.000Z"
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

Pass data.nextCursor as cursor to request the next page. A null cursor means there are no more results.

2. Read one company's credit state

Returns the current allowance, scheduled allowance, usage, reservations, effective availability, warnings, and recent ledger activity for one company.

GET /v3/connect/credits/allowances/{companyId}

Request

curl --location '{BASE_URL}/v3/connect/credits/allowances/{COMPANY_ID}' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json'

Response

200 OK

The response data uses the Company credit state schema and adds:

FieldTypeDescription
recentActivityarrayUp to 10 recent ledger transactions for the company.
scheduledEtagstring or nullQuoted scheduled allowance version, for example "4".

The response includes an ETag header containing the quoted current allowance version. When no current allowance exists, the value is "0".

3. Pause active allowance

Blocks new consumption without changing the allowance dates or deleting its history.

POST /v3/connect/credits/allowances/{companyId}/pause

Required headers

Idempotency-Key: pause-{UNIQUE_KEY}
If-Match: "{CURRENT_VERSION}"
Content-Type: application/json

Request

curl --request POST '{BASE_URL}/v3/connect/credits/allowances/{COMPANY_ID}/pause' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: pause-{UNIQUE_KEY}' \
  --header 'If-Match: "3"' \
  --data '{
    "reason": "Commercial subscription suspended"
  }'

reason is required and may contain up to 500 characters.

Response

200 OK

{
  "success": true,
  "data": {
    "companyId": "{COMPANY_ID}",
    "current": {
      "limit": 1000,
      "periodType": "monthly",
      "allowancePeriodId": "period_01",
      "startAt": "2026-08-01T00:00:00.000Z",
      "endAt": "2026-09-01T00:00:00.000Z",
      "status": "paused",
      "version": 4,
      "finalizedUsage": 250,
      "reserved": 20
    },
    "replayed": false
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

The response ETag contains the new current version.

4. Create or replace scheduled allowance

Creates or replaces the single future allowance for a company. At its inclusive startAt, the allowance becomes eligible for activation and receives a new allowancePeriodId when activated.

Activation is asynchronous. A background lifecycle worker currently checks due allowances every 60 seconds, so the allowance can remain scheduled briefly after startAt.

PUT /v3/connect/credits/allowances/{companyId}/scheduled

Required headers

For the first scheduled allowance:

Idempotency-Key: schedule-{UNIQUE_KEY}
If-None-Match: *
Content-Type: application/json

To replace the scheduled allowance:

Idempotency-Key: schedule-{UNIQUE_KEY}
If-Match: "{SCHEDULED_VERSION}"
Content-Type: application/json

Request body

FieldTypeRequiredDescription
limitnumberYesAllowance limit. Must be 0 or greater.
periodTypestringYesmonthly, annual, or custom.
startAtdate-timeYesFuture UTC timestamp.
endAtdate-timeYesUTC timestamp later than startAt.
reasonstringYesReason for the change, up to 500 characters.
planReferencestringNoISV plan or subscription reference, up to 500 characters.
metadataobjectNoPartner metadata associated with the allowance.

Request

curl --request PUT '{BASE_URL}/v3/connect/credits/allowances/{COMPANY_ID}/scheduled' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: schedule-{UNIQUE_KEY}' \
  --header 'If-None-Match: *' \
  --data '{
    "limit": 1500,
    "periodType": "monthly",
    "startAt": "{FUTURE_PERIOD_START_UTC}",
    "endAt": "{FUTURE_PERIOD_END_UTC}",
    "reason": "Subscription renewal",
    "planReference": "plan-enterprise"
  }'

Response

  • 201 Created when using If-None-Match: *.
  • 200 OK when replacing a scheduled allowance.
{
  "success": true,
  "data": {
    "companyId": "{COMPANY_ID}",
    "scheduled": {
      "limit": 1500,
      "periodType": "monthly",
      "planReference": "plan-enterprise",
      "startAt": "2030-01-01T00:00:00.000Z",
      "endAt": "2030-02-01T00:00:00.000Z",
      "status": "scheduled",
      "version": 1,
      "finalizedUsage": 0,
      "reserved": 0
    },
    "replayed": false
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

The response ETag contains the scheduled allowance version.

5. Submit bulk changes

Submits an asynchronous job containing up to 500 allowance operations. Each row is processed independently, so one row failure does not roll back unrelated successful rows.

POST /v3/connect/credits/allowances/bulk

Required headers

Idempotency-Key: bulk-{UNIQUE_KEY}
Content-Type: application/json

Supported operations

OperationTargetMinimum expectedVersion
replace_currentCurrent allowance0; use 0 to create.
replace_scheduledScheduled allowance0; use 0 to create.
cancel_scheduledScheduled allowance1
pauseCurrent allowance1
resumeCurrent allowance1

Replacement rows also require limit, periodType, startAt, and endAt. Action rows contain only operationId, companyId, operation, expectedVersion, and reason.

Within one job:

  • operationId must be unique and contain no more than 200 characters.
  • A company may have only one operation for each target: current or scheduled.
  • Scheduled allowance start times must be in the future.
  • startAt and endAt must be UTC timestamps ending in Z.
  • Undocumented fields are rejected.

Request

curl --request POST '{BASE_URL}/v3/connect/credits/allowances/bulk' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: bulk-{UNIQUE_KEY}' \
  --data '{
    "operations": [
      {
        "operationId": "op-001",
        "companyId": "{COMPANY_ID_1}",
        "operation": "replace_current",
        "expectedVersion": 3,
        "reason": "Plan upgrade",
        "limit": 2000,
        "periodType": "monthly",
        "startAt": "{CURRENT_PERIOD_START_UTC}",
        "endAt": "{CURRENT_PERIOD_END_UTC}",
        "planReference": "plan-enterprise"
      },
      {
        "operationId": "op-002",
        "companyId": "{COMPANY_ID_2}",
        "operation": "pause",
        "expectedVersion": 2,
        "reason": "Subscription suspended"
      }
    ]
  }'

Response

202 Accepted

{
  "success": true,
  "data": {
    "jobId": "{JOB_ID}",
    "status": "accepted",
    "replayed": false,
    "totals": {
      "total": 2,
      "processed": 0,
      "succeeded": 0,
      "failed": 0
    },
    "results": [
      {
        "operationId": "op-001",
        "companyId": "{COMPANY_ID_1}",
        "operation": "replace_current",
        "status": "pending"
      },
      {
        "operationId": "op-002",
        "companyId": "{COMPANY_ID_2}",
        "operation": "pause",
        "status": "pending"
      }
    ],
    "createdAt": "2026-08-12T10:00:00.000Z",
    "updatedAt": "2026-08-12T10:00:00.000Z"
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

Poll the Read bulk job endpoint until the job reaches completed, completed_with_errors, or failed.

6. Read ledger

Returns cursor-paginated immutable credit activity for the authenticated workspace.

GET /v3/connect/credits/transactions

Query parameters

ParameterTypeRequiredDescription
cursorstringNoOpaque cursor from the preceding page.
limitintegerNoNumber of records from 1 to 100.
companyIdstringNoFilter by managed company.
eventTypestringNoFilter by one supported ledger event type.
occurredFromdate-timeNoInclude events at or after this timestamp.
occurredTodate-timeNoInclude events at or before this timestamp. Cannot precede occurredFrom.
correlationIdstringNoFilter by correlation ID.
idempotencyKeystringNoFilter by idempotency key.
requestIdstringNoFilter by Connect request ID.
transactionIdstringNoFilter by ledger transaction ID.
bulkJobIdstringNoFilter by bulk job ID.

Supported eventType values are:

allowance.created
allowance.replaced
allowance.scheduled
allowance.cancelled
allowance.activated
allowance.expired
allowance.superseded
allowance.paused
allowance.resumed
reservation.created
reservation.released
reservation.needs_reconciliation
consumption.finalized
consumption.reversed
correction.created
credit.issued
credit.expired

Request

curl --get '{BASE_URL}/v3/connect/credits/transactions' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json' \
  --data-urlencode 'companyId={COMPANY_ID}' \
  --data-urlencode 'limit=25'

Response

200 OK

{
  "success": true,
  "data": {
    "items": [
      {
        "transactionId": "txn_01",
        "eventType": "allowance.replaced",
        "occurredAt": "2026-08-12T09:00:00.000Z",
        "companyId": "{COMPANY_ID}",
        "amount": 1000,
        "reason": "Plan upgrade",
        "correlationId": "subscription-change-123",
        "idempotencyKey": "allowance-123",
        "requestId": "01K1EXAMPLE000000000000000",
        "actor": {
          "type": "api_key",
          "actorId": "key_01"
        },
        "balanceBefore": {},
        "balanceAfter": {},
        "metadata": {
          "version": 3,
          "status": "active"
        }
      }
    ],
    "nextCursor": null,
    "asOf": "2026-08-12T10:00:00.000Z"
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

A ledger item can also include bulkJobId, originalTransactionId, countryCode, and documentType when relevant.

7. Read ISV pool

Returns the authenticated ISV workspace's current credit-pool snapshot.

GET /v3/connect/credits/pool

Request

curl --location '{BASE_URL}/v3/connect/credits/pool' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json'

Response

200 OK

{
  "success": true,
  "data": {
    "active": 10000,
    "reserved": 200,
    "consumed": 3000,
    "expired": 100,
    "available": 6800,
    "lots": [
      {
        "active": 10000,
        "available": 6800,
        "expiresAt": "2027-08-01T00:00:00.000Z"
      }
    ],
    "asOf": "2026-08-12T10:00:00.000Z",
    "warnings": []
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

8. Resume active allowance

Allows new consumption against a paused allowance when the allowance period has not ended.

POST /v3/connect/credits/allowances/{companyId}/resume

Request

curl --request POST '{BASE_URL}/v3/connect/credits/allowances/{COMPANY_ID}/resume' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: resume-{UNIQUE_KEY}' \
  --header 'If-Match: "4"' \
  --data '{
    "reason": "Subscription restored"
  }'

Response

200 OK

The response has the same shape as Pause active allowance. data.current.status is active, and the response ETag contains the new version.

9. Read bulk job

Returns the current job state and stable row-level outcomes.

GET /v3/connect/credits/allowances/bulk/{jobId}

Request

curl --location '{BASE_URL}/v3/connect/credits/allowances/bulk/{JOB_ID}' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json'

Response

200 OK

The response uses the bulk-job schema returned by Submit bulk changes. Each row has one of these statuses:

StatusMeaning
pendingThe row is waiting to be processed.
processingThe row is being processed.
succeededThe operation completed successfully.
failedThe operation failed; inspect the row's error.code and error.message.

Job status is accepted, processing, completed, completed_with_errors, or failed. An unknown or cross-workspace job returns 404 CONNECT_CREDIT_BULK_JOB_NOT_FOUND.

10. Create or replace active allowance

Creates the first active allowance or fully replaces the current allowance representation.

PUT /v3/connect/credits/allowances/{companyId}/current

Required headers

For the first current allowance:

Idempotency-Key: current-{UNIQUE_KEY}
If-None-Match: *
Content-Type: application/json

To replace the current allowance:

Idempotency-Key: current-{UNIQUE_KEY}
If-Match: "{CURRENT_VERSION}"
Content-Type: application/json

Request

curl --request PUT '{BASE_URL}/v3/connect/credits/allowances/{COMPANY_ID}/current' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: current-{UNIQUE_KEY}' \
  --header 'If-None-Match: *' \
  --data '{
    "limit": 1000,
    "periodType": "monthly",
    "startAt": "{CURRENT_PERIOD_START_UTC}",
    "endAt": "{CURRENT_PERIOD_END_UTC}",
    "reason": "Initial subscription allowance",
    "planReference": "plan-pro"
  }'

startAt cannot be in the future, endAt must be later than startAt, and endAt must be in the future. When replacing an existing current allowance, send the existing startAt unchanged.

Response

  • 201 Created when the current allowance is created.
  • 200 OK when the current allowance is replaced.
{
  "success": true,
  "data": {
    "companyId": "{COMPANY_ID}",
    "current": {
      "limit": 1000,
      "periodType": "monthly",
      "planReference": "plan-pro",
      "allowancePeriodId": "period_01",
      "startAt": "2026-08-01T00:00:00.000Z",
      "endAt": "2026-09-01T00:00:00.000Z",
      "status": "active",
      "version": 1,
      "finalizedUsage": 0,
      "reserved": 0
    },
    "replayed": false
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

The response ETag contains the current allowance version.

11. Cancel scheduled allowance

Cancels the future allowance before it activates. Current allowance state is unchanged.

DELETE /v3/connect/credits/allowances/{companyId}/scheduled

Request

curl --request DELETE '{BASE_URL}/v3/connect/credits/allowances/{COMPANY_ID}/scheduled' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: cancel-schedule-{UNIQUE_KEY}' \
  --header 'If-Match: "1"' \
  --data '{
    "reason": "Renewal was cancelled"
  }'

Response

200 OK

{
  "success": true,
  "data": {
    "companyId": "{COMPANY_ID}",
    "cancelled": true,
    "version": 1,
    "replayed": false
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

The response ETag contains the cancelled scheduled allowance's existing version. Cancellation does not increment that version.

12. Read ledger export status

Returns the state of an asynchronous CSV export job. A completed export includes a temporary download URL.

GET /v3/connect/credits/exports/{exportId}

Request

curl --location '{BASE_URL}/v3/connect/credits/exports/{EXPORT_ID}' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json'

Response

200 OK

{
  "success": true,
  "data": {
    "exportId": "{EXPORT_ID}",
    "status": "completed",
    "format": "csv",
    "asOf": "2026-08-12T10:00:00.000Z",
    "createdAt": "2026-08-12T10:00:00.000Z",
    "completedAt": "2026-08-12T10:01:00.000Z",
    "expiresAt": "2026-08-13T10:01:00.000Z",
    "downloadUrl": "https://example.invalid/temporary-download-url",
    "rowCount": 125
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:01:00.000Z"
  }
}

Export status is accepted, processing, completed, failed, or expired. A failed job can include errorCode; an idempotent replay can include replayed.

13. Request ledger export

Creates an asynchronous, consistent-snapshot CSV export using the supplied ledger filters.

POST /v3/connect/credits/exports

Required headers

Idempotency-Key: export-{UNIQUE_KEY}
Content-Type: application/json

Request body

format must be csv. The optional filters object accepts the same fields as the ledger endpoint except cursor and limit.

Request

curl --request POST '{BASE_URL}/v3/connect/credits/exports' \
  --header 'X-API-Key: {API_KEY}' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: export-{UNIQUE_KEY}' \
  --data '{
    "format": "csv",
    "filters": {
      "companyId": "{COMPANY_ID}",
      "occurredFrom": "2026-08-01T00:00:00.000Z",
      "occurredTo": "2026-08-31T23:59:59.999Z"
    }
  }'

Response

202 Accepted

{
  "success": true,
  "data": {
    "exportId": "{EXPORT_ID}",
    "status": "accepted",
    "format": "csv",
    "asOf": "2026-08-12T10:00:00.000Z",
    "createdAt": "2026-08-12T10:00:00.000Z",
    "completedAt": null,
    "expiresAt": null,
    "downloadUrl": null,
    "replayed": false
  },
  "meta": {
    "requestId": "01K1EXAMPLE000000000000000",
    "timestamp": "2026-08-12T10:00:00.000Z"
  }
}

Poll the Read ledger export status endpoint until the job reaches a terminal state.

Common errors

The following table lists common errors. An endpoint can also return a more specific code describing the failed operation.

HTTP statusExample codeDescription
400CONNECT_VALIDATION_ERRORA path, query, header, or body field is missing or malformed.
400CONNECT_ALLOWANCE_INVALID_COMMANDRequired idempotency or concurrency headers are missing or invalid.
400CONNECT_ALLOWANCE_INVALID_CURSORAn allowance pagination cursor is invalid.
400CONNECT_ALLOWANCE_INVALID_EFFECTIVE_PERIODAllowance effective-period filters are invalid.
400CONNECT_ALLOWANCE_WRITE_LIMIT_BELOW_COMMITTED_USAGEThe new limit is below finalized usage plus active reservations.
400CONNECT_ALLOWANCE_WRITE_START_AT_IMMUTABLEA replacement attempted to change the current period's startAt.
400CONNECT_SCHEDULED_ALLOWANCE_WRITE_INVALID_PERIODScheduled timestamps are invalid or the start time is not in the future.
400CONNECT_CREDIT_BULK_UNSUPPORTED_FIELDA bulk row contains a field that is not part of its operation schema.
400CONNECT_CREDIT_LEDGER_INVALID_CURSORA ledger pagination cursor is invalid.
400CONNECT_CREDIT_LEDGER_INVALID_PERIODoccurredTo precedes occurredFrom.
400CONNECT_CREDIT_LEDGER_INVALID_EVENT_TYPEeventType is not supported.
400CONNECT_CREDIT_EXPORT_IDEMPOTENCY_KEY_REQUIREDThe export request is missing Idempotency-Key.
401CONNECT_AUTH_CONTEXT_MISSINGAuthentication did not provide a workspace context.
403CONNECT_ISV_ACCESS_DENIEDThe workspace is not eligible for Connect ISV APIs.
403CONNECT_FORBIDDEN_INSUFFICIENT_ROLEThe authenticated user cannot perform credit writes.
404CONNECT_COMPANY_NOT_FOUNDThe company is missing or is not visible to the authenticated workspace.
404CONNECT_CREDIT_BULK_JOB_NOT_FOUNDThe bulk job is missing or belongs to another workspace.
404CONNECT_CREDIT_LEDGER_EXPORT_NOT_FOUNDThe export is missing or belongs to another workspace.
409CONNECT_ALLOWANCE_WRITE_IDEMPOTENCY_CONFLICTAn idempotency key was reused with a different request.
409CONNECT_SCHEDULED_ALLOWANCE_WRITE_IDEMPOTENCY_CONFLICTA scheduled-write idempotency key was reused with a different request.
409CONNECT_SCHEDULED_ALLOWANCE_CANCEL_IDEMPOTENCY_CONFLICTA cancellation idempotency key was reused with a different request.
409CONNECT_ALLOWANCE_STATUS_IDEMPOTENCY_CONFLICTA pause or resume idempotency key was reused with a different request.
409CONNECT_CREDIT_LEDGER_EXPORT_IDEMPOTENCY_CONFLICTAn export idempotency key was reused with different filters.
409CONNECT_ALLOWANCE_STATUS_INVALID_STATE_TRANSITIONThe requested pause or resume transition is not allowed.
412CONNECT_ALLOWANCE_WRITE_PRECONDITION_FAILEDIf-Match or If-None-Match does not match current state.
412CONNECT_SCHEDULED_ALLOWANCE_WRITE_PRECONDITION_FAILEDThe scheduled allowance create or replace precondition does not match current state.
412CONNECT_SCHEDULED_ALLOWANCE_CANCEL_PRECONDITION_FAILEDThe scheduled allowance version changed before cancellation.
412CONNECT_ALLOWANCE_STATUS_PRECONDITION_FAILEDThe current allowance version changed before pause or resume.
429CONNECT_RATE_LIMIT_EXCEEDEDThe workspace exceeded the endpoint's rate limit. Use Retry-After before retrying.
502CONNECT_CREDIT_LEDGER_UNAVAILABLEA credit dependency could not complete the request.
504CONNECT_CREDIT_LEDGER_TIMEOUTA credit dependency timed out.

For a stale version, read the resource again, review its latest state, and retry with a new idempotency key and the new version only if the change is still intended.

Rate limits

Rate limits are applied per workspace. Endpoints in the same row share a rate-limit bucket.

EndpointsLimit
Read pool300 requests per minute
List allowances and read one company300 requests per minute
Create or replace current, create or replace scheduled, cancel, pause, and resume60 requests per minute
Submit bulk changes30 requests per minute
Read bulk job120 requests per minute
Read ledger120 requests per minute
Request export and read export status30 requests per minute

When a limit is exceeded, the API returns 429 Too Many Requests and a Retry-After header.

Webhooks

Credit events and delivery behavior are documented separately in ISV Credit Webhooks.