StabisoDocs

API reference

Revenue contracts

IFRS 15 revenue contracts: the customer, the transaction price and the performance obligations with their standalone selling prices; a second person approves the terms, which allocates the price and writes the recognition schedule, and a person records when a point-in-time obligation is satisfied. Nothing here posts yet.

Operation Summary Scope Idempotency-Key
POST /v1/periods/{period_id}/revenue-recognition Run the revenue recognition of a period draft
GET /v1/periods/{period_id}/revenue-recognition/preview Preview the revenue recognition of a period read
GET /v1/revenue-contracts List revenue contracts read
POST /v1/revenue-contracts Create a revenue contract draft required
GET /v1/revenue-contracts/{contract_id} Get a revenue contract read
POST /v1/revenue-contracts/{contract_id}/activate Activate a revenue contract draft
POST /v1/revenue-contracts/{contract_id}/cancel Cancel a revenue contract draft
GET /v1/revenue-contracts/{contract_id}/changes List a revenue contract's changes read
POST /v1/revenue-contracts/{contract_id}/changes Ask for an active revenue contract to end early or be modified draft
POST /v1/revenue-contracts/{contract_id}/changes/preview Preview ending a revenue contract early or modifying it read
GET /v1/revenue-contracts/{contract_id}/schedule Get a revenue contract's recognition schedule read
POST /v1/revenue-obligations/{obligation_id}/satisfy Record that a point-in-time obligation is satisfied draft

POST /v1/periods/{period_id}/revenue-recognition

Run the revenue recognition of a period

Recognise the revenue due by the period end and present the contracts' positions.

Posts at the period end through the approval policy (source rev): the recognition entry (Dr contract liability, naming the contract / Cr the obligation's revenue account) for every schedule line due by the period end, a line from an earlier period marked as a catch-up; then, once that entry is posted, the presentation entry for each contract whose debit position (recognised, not yet billed) changed: Dr contract asset, or the unbilled receivable for a contract whose right to consideration is unconditional / Cr contract liability, reversed on the first day of the next period. The run is incremental: run it again while the period is open (after a late satisfaction or invoice) and it posts only what changed; with nothing to post, run_id is null. A rejected recognition entry releases its lines for the next run. Refused: 404 for an unknown period; 409 when the period is closed or has not started yet (period_not_started), or an earlier recognition entry waits for approval; 422 for an adjustment period, a missing contract account (roles contract_liability, contract_asset, unbilled_receivable), or when the next period is not opened.

Required scope draft (admin implies every scope)
Idempotency-Key not used
Operation id run_revenue_recognition_v1_periods__period_id__revenue_recognition_post

Parameters

In Name Type Required Description
path period_id string (uuid) yes Fiscal period id (GET /v1/entities/{entity}/periods).

Example request

curl -X POST "$ERP_URL/v1/periods/3fa85f64-5717-4562-b3fc-2c963f66afa6/revenue-recognition" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK RecognitionRunOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "run_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "period": "string",
  "recognised": [
    {
      "contract": "string",
      "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "obligation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "line_no": 1,
      "description": "string",
      "revenue_account": "string",
      "currency": "string",
      "amount": "string",
      "functional_amount": "string",
      "billed_part": "string",
      "lines": 1,
      "catch_up": 1
    }
  ],
  "total": "string",
  "exchange_differences": [
    {
      "contract": "string",
      "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "currency": "string",
      "amount": "string"
    }
  ],
  "remeasured": [
    {
      "contract": "string",
      "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "currency": "string",
      "amount": "string",
      "carrying": "string",
      "closing_rate": "string",
      "remeasured": "string",
      "change": "string"
    }
  ],
  "presentation": [
    {
      "contract": "string",
      "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "position": "string",
      "caption": "contract_asset",
      "presented": "string",
      "change": "string"
    }
  ],
  "recognition": {
    "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "status": "string",
    "number": "string",
    "policy": {
      "decision": null,
      "reason": null,
      "rule_id": null,
      "table_id": null
    },
    "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "reason": "string"
  },
  "presentation_entry": {
    "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "status": "string",
    "number": "string",
    "policy": {
      "decision": null,
      "reason": null,
      "rule_id": null,
      "table_id": null
    },
    "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "reason": "string"
  },
  "waiting": [
    {
      "contract": "string",
      "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "currency": "string",
      "rate_date": "2026-09-21",
      "lines": 1,
      "remeasurement": true,
      "note": "string",
      "note_reason": {
        "words": null,
        "code": null,
        "details": null,
        "text": null
      }
    }
  ],
  "notes": [
    "string"
  ],
  "note_reasons": [
    {
      "words": "string",
      "code": "string",
      "details": {},
      "text": "string"
    }
  ],
  "completed": [
    "string"
  ],
  "recognised_through": "2026-09-21",
  "left_for_later": 0
}

GET /v1/periods/{period_id}/revenue-recognition/preview

Preview the revenue recognition of a period

What POST /v1/periods/{period_id}/revenue-recognition would post now; nothing is written.

recognised lists, per obligation, the schedule lines due by the period end and not yet recognised; presentation the contracts whose debit position the period's entries do not present yet. notes says when an earlier recognition entry waits for approval, an earlier open period is to run first or a contract waits for its rate, in English and by code (note_reasons). Refused: 404 for an unknown period; 422 for an adjustment period.

Required scope read (admin implies every scope)
Operation id preview_revenue_recognition_v1_periods__period_id__revenue_recognition_preview_get

Parameters

In Name Type Required Description
path period_id string (uuid) yes Fiscal period id (GET /v1/entities/{entity}/periods).

Example request

curl "$ERP_URL/v1/periods/3fa85f64-5717-4562-b3fc-2c963f66afa6/revenue-recognition/preview" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK RecognitionRunOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "run_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "period": "string",
  "recognised": [
    {
      "contract": "string",
      "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "obligation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "line_no": 1,
      "description": "string",
      "revenue_account": "string",
      "currency": "string",
      "amount": "string",
      "functional_amount": "string",
      "billed_part": "string",
      "lines": 1,
      "catch_up": 1
    }
  ],
  "total": "string",
  "exchange_differences": [
    {
      "contract": "string",
      "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "currency": "string",
      "amount": "string"
    }
  ],
  "remeasured": [
    {
      "contract": "string",
      "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "currency": "string",
      "amount": "string",
      "carrying": "string",
      "closing_rate": "string",
      "remeasured": "string",
      "change": "string"
    }
  ],
  "presentation": [
    {
      "contract": "string",
      "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "position": "string",
      "caption": "contract_asset",
      "presented": "string",
      "change": "string"
    }
  ],
  "recognition": {
    "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "status": "string",
    "number": "string",
    "policy": {
      "decision": null,
      "reason": null,
      "rule_id": null,
      "table_id": null
    },
    "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "reason": "string"
  },
  "presentation_entry": {
    "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "status": "string",
    "number": "string",
    "policy": {
      "decision": null,
      "reason": null,
      "rule_id": null,
      "table_id": null
    },
    "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "reason": "string"
  },
  "waiting": [
    {
      "contract": "string",
      "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "currency": "string",
      "rate_date": "2026-09-21",
      "lines": 1,
      "remeasurement": true,
      "note": "string",
      "note_reason": {
        "words": null,
        "code": null,
        "details": null,
        "text": null
      }
    }
  ],
  "notes": [
    "string"
  ],
  "note_reasons": [
    {
      "words": "string",
      "code": "string",
      "details": {},
      "text": "string"
    }
  ],
  "completed": [
    "string"
  ],
  "recognised_through": "2026-09-21",
  "left_for_later": 0
}

GET /v1/revenue-contracts

List revenue contracts

Revenue contracts, the newest first, each with its obligations. Read-only.

Required scope read (admin implies every scope)
Operation id list_revenue_contracts_v1_revenue_contracts_get

Parameters

In Name Type Required Description
query entity string or null Only this entity's contracts (code or id).
query status "active" | "cancelled" | "completed" | "draft" | "pending_approval" or null Only contracts with this status.
query party_id string (uuid) or null Only this customer's contracts.
query limit integer How many contracts, the newest first. (min 1; max 1000; default 100)

Example request

curl "$ERP_URL/v1/revenue-contracts" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK array of RevenueContractOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

[
  {
    "created_at": "2026-10-04T08:00:00Z",
    "created_by": {
      "id": "user:alice",
      "name": "Alice",
      "type": "human"
    },
    "currency": "CHF",
    "end_date": "2027-12-31",
    "entity": "CH01",
    "id": "8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b",
    "number": "RC-2027-000001",
    "obligations": [],
    "party_code": "C-CH",
    "party_id": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
    "party_name": "Zürich Kunde AG",
    "plan_version": 1,
    "right_to_consideration": "conditional",
    "start_date": "2027-01-01",
    "status": "draft",
    "title": "Platform 2027",
    "transaction_price": "12000.00"
  }
]

POST /v1/revenue-contracts

Create a revenue contract

Create a revenue contract as a draft: the customer, the period, the transaction price (fixed, net of VAT, in the contract's currency, by default the entity's functional currency; revenue is booked in the functional currency, ADR-0050) and its performance obligations, each with its standalone selling price and how it was established (IFRS 15.77-79), or a product whose SSP in force on the start day is taken. Nothing is allocated or scheduled until a second person approves the terms (POST .../{contract_id}/activate). A draft's terms are not edited: cancel it and create a new one. 404 for an unknown entity, customer, product or account; 422 when an obligation's service period is outside the contract's, a product has no SSP in the currency, or an account is not a revenue account. Needs an Idempotency-Key.

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id create_revenue_contract_v1_revenue_contracts_post

Request body

application/json (required): RevenueContractInput

Field Type Required Description
entity string yes Code (or id) of the entity.
party string yes Code (or id) of the customer.
title string yes What the contract is. (min length 1; max length 200)
start_date string (date) yes The first day of the contract.
end_date string (date) yes The last day of the contract.
currency string or null ISO 4217 code of the currency the contract is priced and billed in; default the entity's functional currency. Revenue is recognised in the functional currency: what was billed in advance at the rate it was billed at, what is recognised before it is billed at the rate of the period end (ADR-0050). (pattern ^[A-Z]{3}$)
transaction_price decimal string yes Fixed consideration, net of VAT, in the contract's currency. (greater than 0)
right_to_consideration "conditional" | "unconditional" Whether a debit position (revenue before billing) is a contract asset (conditional, the default: the right depends on more than time) or an unbilled receivable (unconditional, with right_basis); IFRS 15.107-108. (default "conditional")
right_basis string or null Why the right is unconditional. (min length 3; max length 2000)
obligations array of ObligationInput yes What the contract promises. (min items 1; max items 50)

Example request

curl -X POST "$ERP_URL/v1/revenue-contracts" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "end_date": "2027-12-31",
  "entity": "CH01",
  "obligations": [
    {
      "description": "Platform subscription",
      "method": "monthly",
      "pattern": "over_time",
      "ssp": "11000.00",
      "ssp_basis": "List price, sold without discount"
    },
    {
      "description": "Onboarding",
      "pattern": "point_in_time",
      "ssp": "2000.00",
      "ssp_basis": "Day rate times days, sold separately"
    }
  ],
  "party": "C-CH",
  "start_date": "2027-01-01",
  "title": "Platform 2027",
  "transaction_price": "12000.00"
}'

Responses

Status Meaning Body
201 Created RevenueContractOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "created_at": "2026-10-04T08:00:00Z",
  "created_by": {
    "id": "user:alice",
    "name": "Alice",
    "type": "human"
  },
  "currency": "CHF",
  "end_date": "2027-12-31",
  "entity": "CH01",
  "id": "8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b",
  "number": "RC-2027-000001",
  "obligations": [],
  "party_code": "C-CH",
  "party_id": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
  "party_name": "Zürich Kunde AG",
  "plan_version": 1,
  "right_to_consideration": "conditional",
  "start_date": "2027-01-01",
  "status": "draft",
  "title": "Platform 2027",
  "transaction_price": "12000.00"
}

GET /v1/revenue-contracts/{contract_id}

Get a revenue contract

One revenue contract with its obligations, their allocated prices once it is active, and who approved its terms. 404 when it does not exist.

Required scope read (admin implies every scope)
Operation id get_revenue_contract_v1_revenue_contracts__contract_id__get

Parameters

In Name Type Required Description
path contract_id string (uuid) yes Id of the revenue contract (GET /v1/revenue-contracts).

Example request

curl "$ERP_URL/v1/revenue-contracts/8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK RevenueContractOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "created_at": "2026-10-04T08:00:00Z",
  "created_by": {
    "id": "user:alice",
    "name": "Alice",
    "type": "human"
  },
  "currency": "CHF",
  "end_date": "2027-12-31",
  "entity": "CH01",
  "id": "8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b",
  "number": "RC-2027-000001",
  "obligations": [],
  "party_code": "C-CH",
  "party_id": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
  "party_name": "Zürich Kunde AG",
  "plan_version": 1,
  "right_to_consideration": "conditional",
  "start_date": "2027-01-01",
  "status": "draft",
  "title": "Platform 2027",
  "transaction_price": "12000.00"
}

POST /v1/revenue-contracts/{contract_id}/activate

Activate a revenue contract

Ask for the terms of a draft contract to be approved. A human decision: the policy action activate_revenue_contract denies agents (403, naming the rule), and by default a second person approves (POST /v1/approvals/{approval_id}/approve; never the person who created the contract or asked). The approval is bound to the digest of the terms. On approval the transaction price is allocated to the obligations by relative SSP and the schedule is written: a line per month of service for an over-time obligation, one event line for a point-in-time obligation. An organization with one person allows the action in its approval policy, and then a person with the approve scope activates at once. 409 when the contract is not a draft or the customer is not active.

Required scope draft (admin implies every scope)
Idempotency-Key not used
Operation id activate_revenue_contract_v1_revenue_contracts__contract_id__activate_post

Parameters

In Name Type Required Description
path contract_id string (uuid) yes Id of the revenue contract (GET /v1/revenue-contracts).

Example request

curl -X POST "$ERP_URL/v1/revenue-contracts/8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b/activate" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK ActivationOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "contract": {
    "created_at": "2026-10-04T08:00:00Z",
    "created_by": {
      "id": "user:alice",
      "name": "Alice",
      "type": "human"
    },
    "currency": "CHF",
    "end_date": "2027-12-31",
    "entity": "CH01",
    "id": "8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b",
    "number": "RC-2027-000001",
    "obligations": [],
    "party_code": "C-CH",
    "party_id": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
    "party_name": "Zürich Kunde AG",
    "plan_version": 1,
    "right_to_consideration": "conditional",
    "start_date": "2027-01-01",
    "status": "draft",
    "title": "Platform 2027",
    "transaction_price": "12000.00"
  },
  "decision": "allow",
  "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

POST /v1/revenue-contracts/{contract_id}/cancel

Cancel a revenue contract

Cancel a draft contract, or one waiting for approval (its request is withdrawn), with a reason kept in the audit trail. An active contract is not cancelled (409 contract_active_not_cancelled): what it recognised stays, and it is ended early or modified (POST .../{contract_id}/changes). 409 otherwise.

Required scope draft (admin implies every scope)
Idempotency-Key not used
Operation id cancel_revenue_contract_v1_revenue_contracts__contract_id__cancel_post

Parameters

In Name Type Required Description
path contract_id string (uuid) yes Id of the revenue contract (GET /v1/revenue-contracts).

Request body

application/json (required): ContractCancelInput

Field Type Required Description
reason string yes Why it is cancelled. (min length 3; max length 1000)

Example request

curl -X POST "$ERP_URL/v1/revenue-contracts/8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b/cancel" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "The customer signed a different offer"
}'

Responses

Status Meaning Body
200 OK RevenueContractOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "created_at": "2026-10-04T08:00:00Z",
  "created_by": {
    "id": "user:alice",
    "name": "Alice",
    "type": "human"
  },
  "currency": "CHF",
  "end_date": "2027-12-31",
  "entity": "CH01",
  "id": "8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b",
  "number": "RC-2027-000001",
  "obligations": [],
  "party_code": "C-CH",
  "party_id": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
  "party_name": "Zürich Kunde AG",
  "plan_version": 1,
  "right_to_consideration": "conditional",
  "start_date": "2027-01-01",
  "status": "draft",
  "title": "Platform 2027",
  "transaction_price": "12000.00"
}

GET /v1/revenue-contracts/{contract_id}/changes

List a revenue contract's changes

The changes asked for the contract, the oldest first, with the amounts each named, whether it was applied, and the credit notes it made. 404 when the contract does not exist.

Required scope read (admin implies every scope)
Operation id list_revenue_contract_changes_v1_revenue_contracts__contract_id__changes_get

Parameters

In Name Type Required Description
path contract_id string (uuid) yes Id of the revenue contract (GET /v1/revenue-contracts).

Example request

curl "$ERP_URL/v1/revenue-contracts/8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b/changes" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK array of ContractChangeOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

[
  {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "kind": "end",
    "end_date": "2026-09-21",
    "new_price": "string",
    "reason": "string",
    "amounts": {
      "kind": "end",
      "old_price": "string",
      "new_price": "string",
      "old_end_date": "2026-09-21",
      "end_date": "2026-09-21",
      "effective_date": "2026-09-21",
      "earned": "string",
      "recognised": "string",
      "billed": "string",
      "credit_total": "string",
      "to_bill": "string",
      "credits": [
        null
      ],
      "recurring_invoices": [
        null
      ]
    },
    "status": "applied",
    "modification_plan_version": 1,
    "credit_notes": [
      "string"
    ],
    "approved_by": {},
    "approved_at": "2026-09-21T09:30:00Z",
    "created_by": {},
    "created_at": "2026-09-21T09:30:00Z"
  }
]

POST /v1/revenue-contracts/{contract_id}/changes

Ask for an active revenue contract to end early or be modified

Ask a second person to approve a change of an active contract no subscription bills (a subscription's contract changes by the subscription's amendments), as a prospective contract modification (IFRS 15.21(a)): revenue recognised stays, the schedule from the first day not recognised is rewritten.

end ends the contract on end_date, before its last day, by default at what the schedule earned through that day (a part of a month by its days); modify gives it a new price and/or end_date (also a later one) from the first day not recognised. When the new price is below what was billed, the difference is credited on the invoices, newest first (a credit note per invoice, posted with the change under its approval); above it, the rest is billed later. A further promise at its standalone selling price is a new contract (IFRS 15.20).

A human decision: agents are refused (policy action activate_revenue_contract, 403), and a second person approves (POST /v1/approvals/{approval_id}/approve), never the person who asked; approving refuses (409 terms_changed) when revenue was recognised or an invoice posted since. 409 when the contract is not active or a subscription's, an invoice or credit note billing it is not posted, revenue is recognised after end_date, a promise is not delivered or a change waits; 422 for a day outside the term (end), a change that changes nothing or a price of zero.

Required scope draft (admin implies every scope)
Idempotency-Key not used
Operation id request_revenue_contract_change_v1_revenue_contracts__contract_id__changes_post

Parameters

In Name Type Required Description
path contract_id string (uuid) yes Id of the revenue contract (GET /v1/revenue-contracts).

Request body

application/json (required): ContractChangeInput

Field Type Required Description
kind "end" | "modify" yes end: end the contract early, on end_date, before its last day. modify: a new transaction price and/or last day (earlier or later) from effective_date (IFRS 15.21(a)); what the old terms earned before that day stays.
end_date string (date) or null end: the last day of service (required). modify: the new last day; default the current one.
price decimal string or null The transaction price after the change, net of VAT, in the contract's currency. end: default what the schedule earned through end_date (a part of a month by its days); a higher price (a fee for ending early) is recognised on the last day. modify: default the current price. (greater than 0)
effective_date string (date) or null modify only: the day the change takes effect, the day the parties agreed it; default today where the company is (or the first day of the term, when it starts later). Never before the first day whose revenue is not recognised, and on or before the last day. What the schedule earned before it stays, recognised or not (a part of a month by its days); the rest of the new price is spread from it.
reason string yes Why the contract changes. (min length 3; max length 1000)

Example request

curl -X POST "$ERP_URL/v1/revenue-contracts/8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b/changes" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "end_date": "2026-04-30",
  "kind": "end",
  "reason": "The customer gave up the maintenance after four months"
}'

Responses

Status Meaning Body
201 Created ContractChangeAskedOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "change": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "contract_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "kind": "end",
    "end_date": "2026-09-21",
    "new_price": "string",
    "reason": "string",
    "amounts": {
      "kind": "end",
      "old_price": "string",
      "new_price": "string",
      "old_end_date": "2026-09-21",
      "end_date": "2026-09-21",
      "effective_date": "2026-09-21",
      "earned": "string",
      "recognised": "string",
      "billed": "string",
      "credit_total": "string",
      "to_bill": "string",
      "credits": [
        null
      ],
      "recurring_invoices": [
        null
      ]
    },
    "status": "applied",
    "modification_plan_version": 1,
    "credit_notes": [
      "string"
    ],
    "approved_by": {},
    "approved_at": "2026-09-21T09:30:00Z",
    "created_by": {},
    "created_at": "2026-09-21T09:30:00Z"
  },
  "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

POST /v1/revenue-contracts/{contract_id}/changes/preview

Preview ending a revenue contract early or modifying it

What the change would do, worked out from what is posted now; nothing is written. The same refusals as asking for it.

Required scope read (admin implies every scope)
Idempotency-Key not used
Operation id preview_revenue_contract_change_v1_revenue_contracts__contract_id__changes_preview_post

Parameters

In Name Type Required Description
path contract_id string (uuid) yes Id of the revenue contract (GET /v1/revenue-contracts).

Request body

application/json (required): ContractChangeInput

Field Type Required Description
kind "end" | "modify" yes end: end the contract early, on end_date, before its last day. modify: a new transaction price and/or last day (earlier or later) from effective_date (IFRS 15.21(a)); what the old terms earned before that day stays.
end_date string (date) or null end: the last day of service (required). modify: the new last day; default the current one.
price decimal string or null The transaction price after the change, net of VAT, in the contract's currency. end: default what the schedule earned through end_date (a part of a month by its days); a higher price (a fee for ending early) is recognised on the last day. modify: default the current price. (greater than 0)
effective_date string (date) or null modify only: the day the change takes effect, the day the parties agreed it; default today where the company is (or the first day of the term, when it starts later). Never before the first day whose revenue is not recognised, and on or before the last day. What the schedule earned before it stays, recognised or not (a part of a month by its days); the rest of the new price is spread from it.
reason string yes Why the contract changes. (min length 3; max length 1000)

Example request

curl -X POST "$ERP_URL/v1/revenue-contracts/8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b/changes/preview" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "end_date": "2026-04-30",
  "kind": "end",
  "reason": "The customer gave up the maintenance after four months"
}'

Responses

Status Meaning Body
200 OK ContractChangeAmounts
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "kind": "end",
  "old_price": "string",
  "new_price": "string",
  "old_end_date": "2026-09-21",
  "end_date": "2026-09-21",
  "effective_date": "2026-09-21",
  "earned": "string",
  "recognised": "string",
  "billed": "string",
  "credit_total": "string",
  "to_bill": "string",
  "credits": [
    {
      "invoice_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "invoice_number": "string",
      "amount": "string"
    }
  ],
  "recurring_invoices": [
    {
      "template_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "string",
      "end_date": "2026-09-21",
      "ends": true
    }
  ]
}

GET /v1/revenue-contracts/{contract_id}/schedule

Get a revenue contract's recognition schedule

The recognition schedule, by obligation and day: what is revenue when, and whether it was posted. Empty until the contract is active. 404 when the contract does not exist.

Required scope read (admin implies every scope)
Operation id get_revenue_contract_schedule_v1_revenue_contracts__contract_id__schedule_get

Parameters

In Name Type Required Description
path contract_id string (uuid) yes Id of the revenue contract (GET /v1/revenue-contracts).

Example request

curl "$ERP_URL/v1/revenue-contracts/8e1f2a3b-4c5d-4e6f-9a7b-8c9d0e1f2a3b/schedule" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK array of ScheduleLineOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

[
  {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "obligation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "line_no": 1,
    "plan_version": 1,
    "trigger": "event",
    "period_start": "2026-09-21",
    "period_end": "2026-09-21",
    "recognise_on": "2026-09-21",
    "amount": "string",
    "superseded": true,
    "recognised": true,
    "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }
]

POST /v1/revenue-obligations/{obligation_id}/satisfy

Record that a point-in-time obligation is satisfied

Record the day control of a point-in-time obligation transferred to the customer, with the evidence: its schedule line is revenue from that day. A human decision: the policy action satisfy_obligation denies agents (403). 409 unless the contract is active and the obligation is open and at a point in time; 422 for a day in the future or before the contract starts.

Required scope draft (admin implies every scope)
Idempotency-Key not used
Operation id satisfy_revenue_obligation_v1_revenue_obligations__obligation_id__satisfy_post

Parameters

In Name Type Required Description
path obligation_id string (uuid) yes Id of the performance obligation (obligations[].id of the contract).

Request body

application/json (required): SatisfyInput

Field Type Required Description
on string (date) yes The day control transferred.
evidence string yes What shows it: a delivery note, an acceptance, a go-live record. (min length 3; max length 2000)

Example request

curl -X POST "$ERP_URL/v1/revenue-obligations/9f2a3b4c-5d6e-4f7a-8b9c-0d1e2f3a4b5c/satisfy" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "evidence": "Acceptance protocol AP-2027-004",
  "on": "2027-01-20"
}'

Responses

Status Meaning Body
200 OK ObligationOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "line_no": 1,
  "description": "string",
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "pattern": "over_time",
  "method": "monthly",
  "service_start": "2026-09-21",
  "service_end": "2026-09-21",
  "ssp": "string",
  "ssp_basis": "string",
  "allocated_price": "string",
  "revenue_account": "string",
  "status": "cancelled",
  "satisfied_on": "2026-09-21",
  "satisfied_by": {},
  "satisfaction_evidence": "string"
}

Schemas

ActivationOut

Field Type Required Description
contract RevenueContractOut yes The contract after the request.
decision "allow" | "require_approval" yes allow: active now; require_approval: a second person decides (POST /v1/approvals/{approval_id}/approve).
approval_id string (uuid) or null yes The approval request, when one is open.

ContractCancelInput

Field Type Required Description
reason string yes Why it is cancelled. (min length 3; max length 1000)

ContractChangeAmounts

Field Type Required Description
kind "end" | "modify" yes end or modify.
old_price string yes The transaction price before.
new_price string yes The transaction price after.
old_end_date string (date) yes The last day before.
end_date string (date) yes The last day after.
effective_date string (date) yes The first day the new terms apply to: the day after the last day for an early end, the day asked (default today) for a modification. Revenue the old terms earned before it stays.
earned string yes end: what the schedule earned through the last day (a part of a month by its days), spread over the months not recognised yet; what the price adds beyond it is recognised on the last day. modify: the new price, of which what the old terms earned before effective_date stays and the rest is spread from it.
recognised string yes Revenue recognised so far; it stays.
billed string yes What the contract billed, net, before the change.
credit_total string yes What the credit notes credit, net of VAT: what was billed beyond the new price. Zero when the price is not below what was billed.
to_bill string yes What is left to invoice after the change (new price less what stays billed); revenue recognised before it is billed is a contract asset.
credits array of ContractChangeCredit yes A credit note per invoice, dated the day the change is applied.
recurring_invoices array of ContractChangeRecurring yes The recurring invoices that bill the contract past its new last day: they stop on it when the change is applied.

ContractChangeAskedOut

Field Type Required Description
change ContractChangeOut yes The change asked, waiting for approval.
approval_id string (uuid) yes The approval request a second person decides (POST /v1/approvals/{approval_id}/approve); never the person who asked.

ContractChangeCredit

Field Type Required Description
invoice_id string (uuid) yes The invoice the credit note credits.
invoice_number string or null yes Its number.
amount string yes What it credits, net of VAT, in the contract's currency.

ContractChangeInput

Field Type Required Description
kind "end" | "modify" yes end: end the contract early, on end_date, before its last day. modify: a new transaction price and/or last day (earlier or later) from effective_date (IFRS 15.21(a)); what the old terms earned before that day stays.
end_date string (date) or null end: the last day of service (required). modify: the new last day; default the current one.
price decimal string or null The transaction price after the change, net of VAT, in the contract's currency. end: default what the schedule earned through end_date (a part of a month by its days); a higher price (a fee for ending early) is recognised on the last day. modify: default the current price. (greater than 0)
effective_date string (date) or null modify only: the day the change takes effect, the day the parties agreed it; default today where the company is (or the first day of the term, when it starts later). Never before the first day whose revenue is not recognised, and on or before the last day. What the schedule earned before it stays, recognised or not (a part of a month by its days); the rest of the new price is spread from it.
reason string yes Why the contract changes. (min length 3; max length 1000)

ContractChangeOut

Field Type Required Description
id string (uuid) yes Id of the change.
contract_id string (uuid) yes The revenue contract.
kind "end" | "modify" yes end: ended early; modify: a new price and/or last day.
end_date string (date) yes The contract's last day after the change.
new_price string yes The transaction price after the change.
reason string yes Why it was asked.
amounts ContractChangeAmounts yes What the request named.
status "applied" | "pending_approval" | "rejected" yes pending_approval, applied (in force) or rejected.
modification_plan_version integer or null yes The contract's plan version the change made, once applied.
credit_notes array of string yes The numbers of the credit notes it made.
approved_by object or null yes Who approved it.
approved_at string (date-time) or null yes When it was approved, else empty.
created_by object yes Who asked.
created_at string (date-time) yes When it was asked.

ContractChangeRecurring

Field Type Required Description
template_id string (uuid) yes The recurring invoice that bills the contract.
name string yes Its name.
end_date string (date) yes Its last day after the change: the contract's.
ends boolean yes True when nothing is left for it to invoice by then: it ends. False: it keeps running to its new last day.

ContractModificationOut

Field Type Required Description
plan_version integer yes The plan version it started.
effective_date string (date) yes The first day the new terms apply to.
old_price string yes The transaction price before.
new_price string yes The transaction price after.
old_end_date string (date) yes The last day before.
new_end_date string (date) yes The last day after.
reason string yes Why the terms changed, in English.
reason_words Reason or null The same by code (revenueContracts.change), for the screens to word in the person's language: a subscription's early end names the subscription, its last day and the reason the person gave; null for a change worded only in reason.
approved_by object yes Who approved the change.
created_at string (date-time) yes When (UTC).

ExchangeDifferenceItem

Field Type Required Description
contract string yes Number of the revenue contract.
contract_id string (uuid) yes Id of the revenue contract.
currency string yes The contract's currency.
amount string yes The realised exchange difference posted, in the functional currency: positive a gain, negative a loss. A contract in a foreign currency carries its position at historical rates; billing what was recognised before it was billed (or crediting what was billed in advance) at another rate leaves this difference on the contract liability, which the run moves to the exchange gain or loss account.

ObligationInput

Field Type Required Description
description string yes What is promised. (min length 1; max length 500)
product string or null Code (or id) of a product of the entity (GET /v1/products). It gives the revenue account and, when ssp is omitted, the SSP in force on the contract's start day, with its basis.
pattern "over_time" | "point_in_time" yes over_time (revenue as the service is given, over service_start to service_end) or point_in_time (revenue when a person records that control transferred: POST /v1/revenue-obligations/{obligation_id}/satisfy).
method "monthly" | "straight_line" or null Over time: straight_line (by days) or monthly (each calendar month the same, a part of a month by its days); default straight_line. None at a point in time.
service_start string (date) or null Over time: the first day of service; default the contract's.
service_end string (date) or null Over time: the last day of service; default the contract's.
quantity decimal string With a product and no ssp: how many units (seats, days) the obligation is; the product's SSP is per unit, and for a recurring product per month or year, so the obligation's SSP is the unit SSP times the quantity times the months (or years) of its service period. (greater than 0; default "1")
ssp decimal string or null Standalone selling price of the whole obligation, in the contract's currency; required without a product SSP. (greater than 0)
ssp_basis string or null How the SSP was established (IFRS 15.77-79); required with ssp. (min length 3; max length 2000)
revenue_account string or null Revenue account (code or id); default the product's, else the entity's default revenue account.

ObligationOut

Field Type Required Description
id string (uuid) yes Obligation id.
line_no integer yes Position, from 1.
description string yes What is promised.
product_id string (uuid) or null yes The product.
pattern "over_time" | "point_in_time" yes over_time or point_in_time.
method "monthly" | "straight_line" or null yes Over time: the method.
service_start string (date) or null yes Over time: the first day of service.
service_end string (date) or null yes Over time: the last day of service.
ssp string yes Standalone selling price.
ssp_basis string yes How it was established.
allocated_price string or null yes Its part of the transaction price; null until the contract is activated.
revenue_account string yes Code of the revenue account.
status "cancelled" | "open" | "satisfied" yes The status.
satisfied_on string (date) or null yes Point in time: when control transferred.
satisfied_by object or null yes Who recorded it.
satisfaction_evidence string or null yes What shows it.

PresentationItem

Field Type Required Description
contract string yes Number of the revenue contract.
contract_id string (uuid) yes Id of the revenue contract.
position string yes Revenue recognised less billed at the period end, in the functional currency: positive is a debit position (presented as an asset), negative a contract liability (presented where it is).
caption "contract_asset" | "unbilled_receivable" yes Where a debit position is presented: unbilled_receivable when only time must pass before payment is due (the contract's right_to_consideration unconditional), else contract_asset.
presented string yes What the period's entries present after this run.
change string yes What this run posts (or would post) for the contract.

RecognitionItem

Field Type Required Description
contract string yes Number of the revenue contract, e.g. RC-2026-000001.
contract_id string (uuid) yes Id of the revenue contract.
obligation_id string (uuid) yes Id of the performance obligation.
line_no integer yes Position of the obligation in its contract, from 1.
description string yes What the obligation promises.
revenue_account string yes Code of the revenue account credited.
currency string yes The contract's currency, which amount is in.
amount string yes Revenue recognised, in the contract's currency.
functional_amount string yes The same revenue in the entity's functional currency, as booked: for a contract in another currency, what billing in advance covered at the rate it was billed at, the rest at the rate of the period end (ADR-0050).
billed_part string yes Of amount, the part billing in advance covered (booked at the rate the contract liability is carried at); the rest was recognised before it was billed. Equals amount for a contract in the functional currency.
lines integer yes Schedule lines recognised.
catch_up integer yes Of those, lines due before the period began (recognised in this period).

RecognitionRunOut

Field Type Required Description
run_id string (uuid) or null yes Id of the recorded run; null for a preview or when nothing was due.
period string yes The period as YYYY-NN, e.g. 2026-09.
recognised array of RecognitionItem yes Revenue recognised per obligation: the schedule lines due by the period end (time lines of the months through it, satisfied point-in-time obligations).
total string yes Revenue recognised, in the functional currency.
exchange_differences array of ExchangeDifferenceItem Realised exchange differences of contracts in a foreign currency, posted with the recognition entry (ADR-0050).
remeasured array of RemeasurementItem Unbilled receivables in a foreign currency remeasured at the closing rate (monetary items, IAS 21.23), posted with the presentation entry (ADR-0050).
presentation array of PresentationItem yes The contracts whose presentation changes: each one's debit position at the period end and the change posted (reversed on the first day of the next period).
recognition SubmitResult or null yes The recognition entry (Dr contract liability / Cr revenue, and any exchange difference) with the approval policy decision; null when nothing was due.
presentation_entry SubmitResult or null yes The presentation entry (Dr contract asset or unbilled receivable / Cr contract liability, auto-reversing); null when no presentation changes, or when the recognition entry waits for approval (run again once it is decided).
waiting array of WaitingItem Contracts in a foreign currency left for a later run because the ECB rate of the period end is not published yet (a run before the period's last day): their lines due stay due and their unbilled receivable is not remeasured; everything else is recognised as usual (ADR-0050).
notes array of string What the run left for later or to see to first, in English words.
note_reasons array of Reason notes by code, in the same order (erp.contracts.words.RECOGNITION_NOTES): the screens word each as periodClose.recognitionNote.<code> from its details.
completed array of string The contracts the run completed: their last day is before today and on or before the period end, and every schedule line in force is recognised by a posted entry.
recognised_through string (date) yes The last day whose revenue the run recognises: the period end once it has passed, else yesterday (revenue is recognised only once it is earned).
left_for_later integer Schedule lines of the period whose day has not passed yet: left for a run after it (a run of the current period before its last day). (default 0)

RemeasurementItem

Field Type Required Description
contract string yes Number of the revenue contract.
contract_id string (uuid) yes Id of the revenue contract.
currency string yes The contract's currency.
amount string yes The unbilled receivable in the contract's currency.
carrying string yes What it is carried at in the functional currency (the rates it was recognised at).
closing_rate string yes The ECB rate of the period end. (pattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$)
remeasured string yes amount at the closing rate.
change string yes What this run posts (or would post): Dr or Cr the unbilled receivable against unrealised exchange differences, reversed on the first day of the next period.

RevenueContractInput

Field Type Required Description
entity string yes Code (or id) of the entity.
party string yes Code (or id) of the customer.
title string yes What the contract is. (min length 1; max length 200)
start_date string (date) yes The first day of the contract.
end_date string (date) yes The last day of the contract.
currency string or null ISO 4217 code of the currency the contract is priced and billed in; default the entity's functional currency. Revenue is recognised in the functional currency: what was billed in advance at the rate it was billed at, what is recognised before it is billed at the rate of the period end (ADR-0050). (pattern ^[A-Z]{3}$)
transaction_price decimal string yes Fixed consideration, net of VAT, in the contract's currency. (greater than 0)
right_to_consideration "conditional" | "unconditional" Whether a debit position (revenue before billing) is a contract asset (conditional, the default: the right depends on more than time) or an unbilled receivable (unconditional, with right_basis); IFRS 15.107-108. (default "conditional")
right_basis string or null Why the right is unconditional. (min length 3; max length 2000)
obligations array of ObligationInput yes What the contract promises. (min items 1; max items 50)

RevenueContractOut

Field Type Required Description
id string (uuid) yes Contract id.
entity string yes Entity code.
number string yes RC-2027-000001, per entity and year of the start date.
party_id string (uuid) yes The customer's id.
party_code string yes The customer's code.
party_name string yes The customer's name.
title string yes What the contract is.
currency string yes The currency it is priced and billed in; revenue is booked in the entity's functional currency (ADR-0050).
start_date string (date) yes The first day.
end_date string (date) yes The last day.
transaction_price string yes Fixed consideration, net of VAT.
right_to_consideration string yes conditional or unconditional.
right_basis string or null yes Why the right is unconditional.
status "active" | "cancelled" | "completed" | "draft" | "pending_approval" yes The status.
plan_version integer yes The schedule's current plan version.
terms_digest string or null yes SHA-256 of the approved terms.
approved_by object or null yes Who approved the terms.
approved_at string (date-time) or null yes When (UTC).
cancel_reason string or null yes Why it was cancelled.
obligations array of ObligationOut yes What it promises, by line.
modifications array of ContractModificationOut Changes of the active contract's terms, accounted for prospectively (ADR-0047), by plan version.
created_by object yes Who created it.
created_at string (date-time) yes When (UTC).

SatisfyInput

Field Type Required Description
on string (date) yes The day control transferred.
evidence string yes What shows it: a delivery note, an acceptance, a go-live record. (min length 3; max length 2000)

ScheduleLineOut

Field Type Required Description
id string (uuid) yes Schedule line id.
obligation_id string (uuid) yes The obligation.
line_no integer yes The obligation's line number.
plan_version integer yes The plan version it belongs to.
trigger "event" | "time" yes time or event.
period_start string (date) or null yes A time line: the first day it covers.
period_end string (date) or null yes A time line: the last day it covers.
recognise_on string (date) or null yes The day it is revenue; an event line: null until the obligation is satisfied.
amount string yes Revenue, in the contract's currency.
superseded boolean yes Replaced by a later plan version.
recognised boolean yes Posted as revenue.
journal_entry_id string (uuid) or null yes The recognition entry.

WaitingItem

Field Type Required Description
contract string yes Number of the revenue contract.
contract_id string (uuid) yes Id of the revenue contract.
currency string yes The contract's currency.
rate_date string (date) yes The day whose ECB rate the run needs and does not have yet (the period end): run again once it is published.
lines integer yes Schedule lines due that wait (revenue recognised before it is billed is booked at the period end's rate); 0 when only the remeasurement waits.
remeasurement boolean yes Whether the unbilled receivable's remeasurement at the closing rate waits.
note string yes The same, in English words (also in notes).
note_reason Reason yes note by code (periodClose.recognitionNote.waiting_lines, waiting_remeasurement or waiting_both, with contract, currency, date and, for lines, their count).
Stabiso, the Enterprise System of Record · generated from the code and its guides · release 20b7dd5b0c4d