API Reference

Services

External CRUD for catalog services, priceable attributes, list-price rate cards, and pricing logic.

Services

Prefix: /api/v1/external/services

See Overview for authentication, pagination, and errors.

The examples below treat an LLM model as a service (gpt-4o). Token charges use priceable attributes named Input_Tokens and Output_Tokens. Raw token counts arrive as input attributes (Prompt_Tokens, Completion_Tokens). Pricing logic turns rate-card unit rates into a final charge (the same concept as Computations in the product UI).

Endpoint summary

MethodPath
GET/services
GET/services/{serviceId}
POST/services
PUT/services/{serviceId}
DELETE/services/{serviceId}
GET/services/{serviceId}/priceable-attributes
GET/services/{serviceId}/priceable-attributes/{attributeId}
POST/services/{serviceId}/priceable-attributes
PUT/services/{serviceId}/priceable-attributes/{attributeId}
DELETE/services/{serviceId}/priceable-attributes/{attributeId}
GET/services/{serviceId}/rate-cards
GET/services/{serviceId}/rate-cards/{currency}
GET/services/{serviceId}/rate-cards/{currency}/versions
POST/services/{serviceId}/rate-cards
PUT/services/{serviceId}/rate-cards/{currency}
DELETE/services/{serviceId}/rate-cards/{currency}
GET/services/{serviceId}/pricing-logic
GET/services/{serviceId}/pricing-logic/{pricingLogicId}
POST/services/{serviceId}/pricing-logic
PUT/services/{serviceId}/pricing-logic/{pricingLogicId}
DELETE/services/{serviceId}/pricing-logic/{pricingLogicId}

Service CRUD

List services

GET /api/v1/external/services?page=0&size=20&q=gpt
Authorization: Bearer YOUR_API_TOKEN
QueryDescription
page0-based page index (default 0)
sizePage size (default 20, max 20)
qOptional search on name, code, label

List rows are service headers only — nested attributes, rate cards, and pricing logic are omitted. Envelope and __r objects: Overview.

Response 200

{
  "requestId": "req-1",
  "success": true,
  "status": 200,
  "errors": [],
  "data": {
    "content": [
      {
        "__type__": "Service",
        "Id": "e6cbd28a-f34c-482e-8da5-34e21dbd5eb7",
        "Name": "gpt-4o",
        "Label": "GPT-4o",
        "Code": "MODEL-GPT-4O",
        "ApprovalStatus": "fe07e71d-cba4-4316-9c7c-4935c3adec34",
        "ApprovalStatus__r": { "Name": "Approved" }
      }
    ],
    "totalElements": 1,
    "size": 20,
    "number": 0
  }
}

Get service

GET /api/v1/external/services/{serviceId}
Authorization: Bearer YOUR_API_TOKEN

Returns scalar fields plus current priceableAttributes[], inputAttributes[], rateCards[] (one current card per currency), and pricingLogic[].

Response 200

{
  "id": "e6cbd28a-f34c-482e-8da5-34e21dbd5eb7",
  "name": "gpt-4o",
  "label": "GPT-4o",
  "code": "MODEL-GPT-4O",
  "serviceType": "Usage",
  "serviceStatus": "Active",
  "currency": "USD",
  "priceableAttributes": [
    {
      "id": "2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77",
      "name": "Input_Tokens",
      "label": "Input Tokens",
      "dimensionDataType": "Number",
      "isMeterDimension": false,
      "dimValues": []
    },
    {
      "id": "3a9c5d27-8e4a-4b63-c2f9-7d1e0b4c6f88",
      "name": "Output_Tokens",
      "label": "Output Tokens",
      "dimensionDataType": "Number",
      "isMeterDimension": false,
      "dimValues": []
    }
  ],
  "inputAttributes": [
    {
      "id": "4b0d6e38-9f5b-4c74-d3a0-8e2f1c5d7a99",
      "name": "Prompt_Tokens",
      "label": "Prompt Tokens",
      "dimensionDataType": "Number",
      "dimValues": []
    }
  ],
  "rateCards": [
    {
      "currency": "USD",
      "versionNo": 1,
      "isCurrent": true,
      "fromDate": "2026-01-01",
      "rows": [
        {
          "id": "6d2f8a5a-1b7d-4e96-f5c2-0a4b3e7f9c11",
          "priceDimId": "2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77",
          "label": "Input token unit rate",
          "usageType": "Charge",
          "priceMethod": "QUANTITY",
          "unitRate": 0.0025,
          "attributeValues": []
        }
      ]
    }
  ],
  "pricingLogic": [
    {
      "id": "9d1e7f23-4a6b-4c85-8e30-1b7d5f2a9c64",
      "name": "Input token pricing",
      "seqNo": 1,
      "priceOutput": "Price_for_Input_Tokens",
      "transactionDimension": "Customer",
      "usageType": "Charge",
      "chargeType": "Usage",
      "steps": [
        { "name": "Input_Tokens_Converted", "label": "Input Tokens Converted", "formula": "(Prompt_Tokens / 1000)" },
        { "name": "Input_Tokens_Qty", "label": "Input Tokens Qty", "formula": "Ceil(Input_Tokens_Converted)" },
        { "name": "Price_for_Input_Tokens", "label": "Price for Input Tokens", "formula": "Price(Input_Tokens, Input_Tokens_Qty)" }
      ]
    }
  ]
}

Create service

POST /api/v1/external/services
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

name is required and must be unique (409 otherwise). Nested priceableAttributes, inputAttributes, rateCards, and pricingLogic are optional and persisted in that order.

Request — catalog a model with input/output token priceables, quantity inputs, list-price rate cards, and pricing logic for input tokens.

{
  "name": "gpt-4o",
  "label": "GPT-4o",
  "code": "MODEL-GPT-4O",
  "currency": "USD",
  "serviceType": "Usage",
  "priceableAttributes": [
    { "name": "Input_Tokens", "label": "Input Tokens", "dimensionDataType": "Number" },
    { "name": "Output_Tokens", "label": "Output Tokens", "dimensionDataType": "Number" }
  ],
  "inputAttributes": [
    { "name": "Prompt_Tokens", "label": "Prompt Tokens", "dimensionDataType": "Number" },
    { "name": "Completion_Tokens", "label": "Completion Tokens", "dimensionDataType": "Number" }
  ],
  "rateCards": [
    {
      "currency": "USD",
      "rows": [
        {
          "priceMethod": "QUANTITY",
          "priceDimName": "Input_Tokens",
          "label": "Input token unit rate",
          "unitRate": 0.0025,
          "usageType": "Charge",
          "attributeValues": []
        },
        {
          "priceMethod": "QUANTITY",
          "priceDimName": "Output_Tokens",
          "label": "Output token unit rate",
          "unitRate": 0.01,
          "usageType": "Charge",
          "attributeValues": []
        }
      ]
    }
  ],
  "pricingLogic": [
    {
      "name": "Input token pricing",
      "priceOutput": "Price_for_Input_Tokens",
      "transactionDimension": "Customer",
      "usageType": "Charge",
      "chargeType": "Usage",
      "steps": [
        { "name": "Input_Tokens_Converted", "label": "Input Tokens Converted", "formula": "Prompt_Tokens / 1000" },
        { "name": "Input_Tokens_Qty", "label": "Input Tokens Qty", "formula": "Ceil(Input_Tokens_Converted)" },
        { "name": "Price_for_Input_Tokens", "label": "Price for Input Tokens", "formula": "Price(Input_Tokens, Input_Tokens_Qty)" }
      ]
    }
  ]
}

Response 201 — the full service detail, identical in shape to Get service.

Notes:

  • Input_Tokens / Output_Tokens are priceable attributes: each owns rate-card rows and is the first argument to Price(...).
  • Prompt_Tokens / Completion_Tokens are input attributes: rating supplies their numeric values.
  • transactionDimension (Customer above) is a TRANSACTION dimension. If it does not exist yet, create pricing logic creates it.
  • Step names and priceOutput must match [A-Za-z_][A-Za-z0-9_]* (use underscores, not spaces).

Update service

PUT /api/v1/external/services/{serviceId}
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

Updates scalar fields. If priceableAttributes, inputAttributes, rateCards, or pricingLogic are present, those collections are replaced. Omit an array to leave it unchanged.

Request — rename the display label and description only.

{
  "label": "GPT-4o (Nov 2026)",
  "description": "OpenAI GPT-4o, November 2026 snapshot",
  "serviceStatus": "Active"
}

Response 200 — the full service detail, identical in shape to Get service.

Delete service

DELETE /api/v1/external/services/{serviceId}
Authorization: Bearer YOUR_API_TOKEN

Deletes nested pricing logic, rate cards, and dimensions.

Response 204 — no body.

Response 409 if any contract service still references the catalog service.

{
  "status": 409,
  "error": "Conflict",
  "message": "Service is referenced by one or more contract services",
  "path": "uri=/api/v1/external/services/e6cbd28a-f34c-482e-8da5-34e21dbd5eb7"
}

Priceable attributes

Priceable attributes are the charge lines on the model (for example Input_Tokens, Output_Tokens). Rate-card rows attach to them via priceDimName / priceDimId.

Input attributes use the same body shape under inputAttributes on composite service create/update (type INPUT). They are returned on GET service; there is no separate nested CRUD path for them.

List priceable attributes

GET /api/v1/external/services/{serviceId}/priceable-attributes?page=0&size=20
Authorization: Bearer YOUR_API_TOKEN

Response 200

{
  "content": [
    {
      "id": "2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77",
      "name": "Input_Tokens",
      "label": "Input Tokens",
      "dimensionDataType": "Number",
      "isContractInput": false,
      "isMeterDimension": false,
      "dimValues": []
    }
  ],
  "page": 0,
  "size": 20,
  "totalElements": 1,
  "totalPages": 1
}

Get priceable attribute

GET /api/v1/external/services/{serviceId}/priceable-attributes/{attributeId}
Authorization: Bearer YOUR_API_TOKEN

Response 200

{
  "id": "2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77",
  "name": "Input_Tokens",
  "label": "Input Tokens",
  "dimensionDataType": "Number",
  "isContractInput": false,
  "isMeterDimension": false,
  "dimValues": []
}

Create priceable attribute

POST /api/v1/external/services/{serviceId}/priceable-attributes
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

name and dimensionDataType are required.

Request

{
  "name": "Output_Tokens",
  "label": "Output Tokens",
  "dimensionDataType": "Number",
  "isContractInput": false,
  "isMeterDimension": false,
  "dimValues": []
}

Response 201

{
  "id": "3a9c5d27-8e4a-4b63-c2f9-7d1e0b4c6f88",
  "name": "Output_Tokens",
  "label": "Output Tokens",
  "dimensionDataType": "Number",
  "isContractInput": false,
  "isMeterDimension": false,
  "dimValues": []
}

Update priceable attribute

PUT /api/v1/external/services/{serviceId}/priceable-attributes/{attributeId}
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

Request

{
  "name": "Output_Tokens",
  "label": "Completion Tokens",
  "dimensionDataType": "Number",
  "dimValues": [{ "label": "US", "value": "US" }]
}

Response 200

{
  "id": "3a9c5d27-8e4a-4b63-c2f9-7d1e0b4c6f88",
  "name": "Output_Tokens",
  "label": "Completion Tokens",
  "dimensionDataType": "Number",
  "dimValues": [{ "label": "US", "value": "US" }]
}

Delete priceable attribute

DELETE /api/v1/external/services/{serviceId}/priceable-attributes/{attributeId}
Authorization: Bearer YOUR_API_TOKEN

Response 204 — no body.

Response 409 if a current rate-card row still uses that priceDimId.

{
  "status": 409,
  "error": "Conflict",
  "message": "Priceable attribute is referenced by a current rate card",
  "path": "uri=/api/v1/external/services/e6cbd28a-f34c-482e-8da5-34e21dbd5eb7/priceable-attributes/2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77"
}

Metered attributes (usage counters)

Set isMeterDimension: true when rating must accumulate usage across transactions and price against that running counter — not just the quantity on a single event.

Typical use case: first N units free per period, then charge the rest. For example, the first 1,000 API calls per month are free; anything above that is billed.

FieldRole
isMeterDimensionWhen true, the platform keeps a dimension meter (counter + optional limit) for this priceable attribute per contract service / account. Rating loads the previous counter, applies the new usage, and writes the updated meter back.
meterResetFrequencyPicklist name that defines when the counter resets: Daily, Weekly, Fortnightly, Monthly, Quarterly, Half Yearly, Yearly. Required for a meaningful free-allowance period.

Without a metered attribute, each rating run only sees the current request's quantity — it cannot know that 800 of the free 1,000 were already used earlier in the month.

Request — metered API usage with a monthly free allowance:

{
  "name": "API_Calls",
  "label": "API Calls",
  "dimensionDataType": "Number",
  "isMeterDimension": true,
  "meterResetFrequency": "Monthly"
}

Response 201

{
  "id": "7e3a9b64-2c5d-4f81-a70b-3d6e8f1c4a25",
  "name": "API_Calls",
  "label": "API Calls",
  "dimensionDataType": "Number",
  "isMeterDimension": true,
  "meterResetFrequency": "Monthly",
  "dimValues": []
}

Pair a metered priceable with a TIERED rate-card row: tier 1 covers the free band (unit rate 0), later tiers charge overage. You can also set resetFrequency on the rate-card row (same picklist names); if omitted, rating falls back to the attribute's meterResetFrequency.

{
  "priceMethod": "TIERED",
  "priceDimName": "API_Calls",
  "label": "Monthly API calls (first 1000 free)",
  "usageType": "Charge",
  "resetFrequency": "Monthly",
  "rateCardTiers": [
    { "tierNum": 1, "tierMinVal": 0, "tierMaxVal": 1000, "tierUnitRate": 0, "flatRate": false },
    { "tierNum": 2, "tierMinVal": 1000, "tierMaxVal": null, "tierUnitRate": 0.01, "flatRate": false }
  ],
  "attributeValues": []
}

How it behaves at rating time:

  1. Meter for API_Calls is loaded for the current Monthly window (or created at 0 if new).
  2. New usage is added to the counter; tiered pricing applies across the filled volume (free band first, then paid).
  3. Updated counter is persisted so the next call in the same month continues from where the last left off.
  4. When the period rolls, the counter starts over.

Rate cards (list price)

A rate card is one currency's current price matrix for the service.

Rate card write body

Rate cards are written on both catalog services and contract-service exceptions with the same body:

{
  "currency": "USD",
  "rows": [
    {
      "priceMethod": "FLAT_RATE",
      "priceDimName": "Usage",
      "label": "Monthly subscription",
      "flatRate": 99.0,
      "attributeValues": []
    }
  ]
}

Common row fields: label (required), priceDimId or priceDimName, description, dynamicDescription, taxCode, usageType (Charge or Payout), billingAccountId, priceMethod (required), attributeValues.

attributeValues may be omitted (treated as []) or empty. Each entry is { "attributeName", "attributeValue" }. rows must contain at least one row.

Send only the rate fields for that priceMethod. Extra fields return 400.

FLAT_RATE

{
  "priceMethod": "FLAT_RATE",
  "priceDimName": "Usage",
  "label": "Monthly subscription",
  "flatRate": 99.0,
  "attributeValues": []
}

TIERED

{
  "priceMethod": "TIERED",
  "priceDimName": "Usage",
  "label": "Volume tiers",
  "resetFrequency": "Monthly",
  "rateCardTiers": [
    { "tierNum": 1, "tierMinVal": 0, "tierMaxVal": 100, "tierUnitRate": 1.5, "flatRate": false }
  ],
  "attributeValues": [{ "attributeName": "Region", "attributeValue": "US" }]
}

rateCardTiers is required and non-empty. flatRate on a tier is a band-level flag, not the row-level flatRate.

resetFrequency is a Meter Reset Frequency picklist name (Daily, Weekly, Monthly, …). Use it with a metered priceable attribute when tiers depend on a period counter (for example first N free per month). See Metered attributes.

QUANTITY

{
  "priceMethod": "QUANTITY",
  "priceDimName": "Usage",
  "label": "Per unit",
  "unitRate": 0.25,
  "attributeValues": []
}

AMOUNT

{
  "priceMethod": "AMOUNT",
  "priceDimName": "Usage",
  "label": "Percent of amount",
  "percentageRate": 2.5,
  "attributeValues": []
}

NO_PRICE

{
  "priceMethod": "NO_PRICE",
  "priceDimName": "Usage",
  "label": "Included",
  "attributeValues": []
}

Rate-card responses echo the resolved priceDimId rather than priceDimName, and add versionNo, isCurrent, fromDate, and toDate.

List rate cards

GET /api/v1/external/services/{serviceId}/rate-cards?page=0&size=20
Authorization: Bearer YOUR_API_TOKEN

Returns the current card per currency.

Response 200

{
  "content": [
    {
      "currency": "USD",
      "versionNo": 1,
      "isCurrent": true,
      "fromDate": "2026-01-01",
      "rows": [
        {
          "id": "6d2f8a5a-1b7d-4e96-f5c2-0a4b3e7f9c11",
          "priceDimId": "2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77",
          "label": "Input token unit rate",
          "usageType": "Charge",
          "priceMethod": "QUANTITY",
          "unitRate": 0.0025,
          "attributeValues": []
        }
      ]
    }
  ],
  "page": 0,
  "size": 20,
  "totalElements": 1,
  "totalPages": 1
}

Get rate card by currency

GET /api/v1/external/services/{serviceId}/rate-cards/USD
Authorization: Bearer YOUR_API_TOKEN

Response 200

{
  "currency": "USD",
  "versionNo": 2,
  "isCurrent": true,
  "fromDate": "2026-07-01",
  "rows": [
    {
      "id": "6d2f8a5a-1b7d-4e96-f5c2-0a4b3e7f9c11",
      "priceDimId": "2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77",
      "label": "Input token unit rate",
      "usageType": "Charge",
      "priceMethod": "QUANTITY",
      "unitRate": 0.003,
      "attributeValues": []
    }
  ]
}

Returns 404 when that currency has no current card.

List rate-card versions

GET /api/v1/external/services/{serviceId}/rate-cards/USD/versions?page=0&size=20
Authorization: Bearer YOUR_API_TOKEN

Response 200

{
  "content": [
    {
      "currency": "USD",
      "versionNo": 2,
      "isCurrent": true,
      "fromDate": "2026-07-01",
      "rows": [
        { "priceDimId": "2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77", "label": "Input token unit rate", "priceMethod": "QUANTITY", "unitRate": 0.003, "attributeValues": [] }
      ]
    },
    {
      "currency": "USD",
      "versionNo": 1,
      "isCurrent": false,
      "fromDate": "2026-01-01",
      "toDate": "2026-06-30",
      "rows": [
        { "priceDimId": "2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77", "label": "Input token unit rate", "priceMethod": "QUANTITY", "unitRate": 0.0025, "attributeValues": [] }
      ]
    }
  ],
  "page": 0,
  "size": 20,
  "totalElements": 2,
  "totalPages": 1
}

Create rate card

POST /api/v1/external/services/{serviceId}/rate-cards
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

Adds a card for a new currency. Returns 409 if that currency already has a current card.

Request

{
  "currency": "EUR",
  "rows": [
    {
      "priceMethod": "QUANTITY",
      "priceDimName": "Input_Tokens",
      "label": "Per 1K input tokens",
      "usageType": "Charge",
      "unitRate": 0.0023,
      "attributeValues": []
    }
  ]
}
curl -sS -X POST "https://YOUR_TENANT_HOST/api/v1/external/services/e6cbd28a-f34c-482e-8da5-34e21dbd5eb7/rate-cards" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "EUR",
    "rows": [{
      "priceMethod": "QUANTITY",
      "priceDimName": "Input_Tokens",
      "label": "Per 1K input tokens",
      "unitRate": 0.0023,
      "attributeValues": []
    }]
  }'

Response 201

{
  "currency": "EUR",
  "versionNo": 1,
  "isCurrent": true,
  "fromDate": "2026-08-31",
  "rows": [
    {
      "id": "8f4a0c76-3d9f-4a18-b82d-5f7c1e9b0a33",
      "priceDimId": "2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77",
      "label": "Per 1K input tokens",
      "usageType": "Charge",
      "priceMethod": "QUANTITY",
      "unitRate": 0.0023,
      "attributeValues": []
    }
  ]
}

Update rate card

PUT /api/v1/external/services/{serviceId}/rate-cards/USD
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

Replaces the card on a draft service, or creates a new version on an approved service. The currency in the body must match the path segment.

Request

{
  "currency": "USD",
  "rows": [
    {
      "priceMethod": "QUANTITY",
      "priceDimName": "Input_Tokens",
      "label": "Input token unit rate",
      "unitRate": 0.003,
      "attributeValues": []
    },
    {
      "priceMethod": "QUANTITY",
      "priceDimName": "Output_Tokens",
      "label": "Output token unit rate",
      "unitRate": 0.012,
      "attributeValues": []
    }
  ]
}

Response 200

{
  "currency": "USD",
  "versionNo": 2,
  "isCurrent": true,
  "fromDate": "2026-08-31",
  "rows": [
    {
      "id": "1c7e5b90-6a2d-4f43-9b1c-7e0d4a8f2b56",
      "priceDimId": "2f8b4c16-7d39-4a52-b1e8-6c0f9a3d5e77",
      "label": "Input token unit rate",
      "priceMethod": "QUANTITY",
      "unitRate": 0.003,
      "attributeValues": []
    },
    {
      "id": "2d8f6c01-7b3e-4054-ac2d-8f1e5b9a3c67",
      "priceDimId": "3a9c5d27-8e4a-4b63-c2f9-7d1e0b4c6f88",
      "label": "Output token unit rate",
      "priceMethod": "QUANTITY",
      "unitRate": 0.012,
      "attributeValues": []
    }
  ]
}

Delete rate card

DELETE /api/v1/external/services/{serviceId}/rate-cards/USD
Authorization: Bearer YOUR_API_TOKEN

Soft-deletes rows, tiers, and attribute values for that currency.

Response 204 — no body.


Pricing logic

Pricing logic is the external name for a service rate computation: ordered formula steps that compute a charge from rate cards and inputs (the same idea as Computation steps in the UI).

Body shape

FieldRequiredDescription
nameYesComputation name
priceOutputYesStep name that holds the final numeric price
transactionDimensionYesTRANSACTION dimension name (who is billed). Auto-created if missing
usageTypeNoCharge (default) or Payout
chargeTypeNoPicklist name: Usage, Subscription, All, or OTC
stepsYesOrdered steps; each has name, optional label, and formula

Supported formulas

PatternExample
Binary arithmeticPrompt_Tokens / 1000, A + B, A - B, A * B
Unary mathCeil(Input_Tokens_Converted), Floor(X), Round(X)
Rate-card lookupPrice(Input_Tokens, Input_Tokens_Qty) — first arg is a priceable attribute name
Literals"LLM_Usage", 1000

List pricing logic

GET /api/v1/external/services/{serviceId}/pricing-logic?page=0&size=20
Authorization: Bearer YOUR_API_TOKEN

Response 200

{
  "content": [
    {
      "id": "9d1e7f23-4a6b-4c85-8e30-1b7d5f2a9c64",
      "name": "Input token pricing",
      "seqNo": 1,
      "priceOutput": "Price_for_Input_Tokens",
      "transactionDimension": "Customer",
      "usageType": "Charge",
      "chargeType": "Usage",
      "steps": [
        { "name": "Input_Tokens_Converted", "label": "Input Tokens Converted", "formula": "(Prompt_Tokens / 1000)" },
        { "name": "Input_Tokens_Qty", "label": "Input Tokens Qty", "formula": "Ceil(Input_Tokens_Converted)" },
        { "name": "Price_for_Input_Tokens", "label": "Price for Input Tokens", "formula": "Price(Input_Tokens, Input_Tokens_Qty)" }
      ]
    }
  ],
  "page": 0,
  "size": 20,
  "totalElements": 1,
  "totalPages": 1
}

Get pricing logic

GET /api/v1/external/services/{serviceId}/pricing-logic/{pricingLogicId}
Authorization: Bearer YOUR_API_TOKEN

Response 200

{
  "id": "9d1e7f23-4a6b-4c85-8e30-1b7d5f2a9c64",
  "name": "Input token pricing",
  "seqNo": 1,
  "priceOutput": "Price_for_Input_Tokens",
  "transactionDimension": "Customer",
  "usageType": "Charge",
  "chargeType": "Usage",
  "steps": [
    { "name": "Input_Tokens_Converted", "label": "Input Tokens Converted", "formula": "(Prompt_Tokens / 1000)" },
    { "name": "Input_Tokens_Qty", "label": "Input Tokens Qty", "formula": "Ceil(Input_Tokens_Converted)" },
    { "name": "Price_for_Input_Tokens", "label": "Price for Input Tokens", "formula": "Price(Input_Tokens, Input_Tokens_Qty)" }
  ]
}

Create pricing logic

POST /api/v1/external/services/{serviceId}/pricing-logic
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

Request — price output tokens.

{
  "name": "Output token pricing",
  "priceOutput": "Price_for_Output_Tokens",
  "transactionDimension": "Customer",
  "usageType": "Charge",
  "chargeType": "Usage",
  "steps": [
    { "name": "Output_Tokens_Converted", "label": "Output Tokens Converted", "formula": "Completion_Tokens / 1000" },
    { "name": "Output_Tokens_Qty", "label": "Output Tokens Qty", "formula": "Ceil(Output_Tokens_Converted)" },
    { "name": "Price_for_Output_Tokens", "label": "Price for Output Tokens", "formula": "Price(Output_Tokens, Output_Tokens_Qty)" }
  ]
}

Response 201 — formulas may come back normalized (for example with parentheses around arithmetic).

{
  "id": "0e2f8a34-5b7c-4d96-af41-2c8e6b0d3f75",
  "name": "Output token pricing",
  "seqNo": 2,
  "priceOutput": "Price_for_Output_Tokens",
  "transactionDimension": "Customer",
  "usageType": "Charge",
  "chargeType": "Usage",
  "steps": [
    { "name": "Output_Tokens_Converted", "label": "Output Tokens Converted", "formula": "(Completion_Tokens / 1000)" },
    { "name": "Output_Tokens_Qty", "label": "Output Tokens Qty", "formula": "Ceil(Output_Tokens_Converted)" },
    { "name": "Price_for_Output_Tokens", "label": "Price for Output Tokens", "formula": "Price(Output_Tokens, Output_Tokens_Qty)" }
  ]
}

Update pricing logic

PUT /api/v1/external/services/{serviceId}/pricing-logic/{pricingLogicId}
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

The body replaces the whole computation, so send the full step list.

Request

{
  "name": "Output token pricing",
  "priceOutput": "Price_for_Output_Tokens",
  "transactionDimension": "Customer",
  "usageType": "Charge",
  "chargeType": "Usage",
  "steps": [
    { "name": "Output_Tokens_Qty", "label": "Output Tokens Qty", "formula": "Ceil(Completion_Tokens / 1000)" },
    { "name": "Price_for_Output_Tokens", "label": "Price for Output Tokens", "formula": "Price(Output_Tokens, Output_Tokens_Qty)" }
  ]
}

Response 200

{
  "id": "0e2f8a34-5b7c-4d96-af41-2c8e6b0d3f75",
  "name": "Output token pricing",
  "seqNo": 2,
  "priceOutput": "Price_for_Output_Tokens",
  "transactionDimension": "Customer",
  "usageType": "Charge",
  "chargeType": "Usage",
  "steps": [
    { "name": "Output_Tokens_Qty", "label": "Output Tokens Qty", "formula": "Ceil((Completion_Tokens / 1000))" },
    { "name": "Price_for_Output_Tokens", "label": "Price for Output Tokens", "formula": "Price(Output_Tokens, Output_Tokens_Qty)" }
  ]
}

Delete pricing logic

DELETE /api/v1/external/services/{serviceId}/pricing-logic/{pricingLogicId}
Authorization: Bearer YOUR_API_TOKEN

Response 204 — no body.