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
| Method | Path |
|---|---|
| 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| Query | Description |
|---|---|
page | 0-based page index (default 0) |
size | Page size (default 20, max 20) |
q | Optional 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_TOKENReturns 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_TOKENname 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_Tokensare priceable attributes: each owns rate-card rows and is the first argument toPrice(...).Prompt_Tokens/Completion_Tokensare input attributes: rating supplies their numeric values.transactionDimension(Customerabove) is a TRANSACTION dimension. If it does not exist yet, create pricing logic creates it.- Step names and
priceOutputmust 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_TOKENUpdates 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_TOKENDeletes 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_TOKENResponse 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_TOKENResponse 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_TOKENname 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_TOKENRequest
{
"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_TOKENResponse 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.
| Field | Role |
|---|---|
isMeterDimension | When 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. |
meterResetFrequency | Picklist 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:
- Meter for
API_Callsis loaded for the current Monthly window (or created at 0 if new). - New usage is added to the counter; tiered pricing applies across the filled volume (free band first, then paid).
- Updated counter is persisted so the next call in the same month continues from where the last left off.
- 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_TOKENReturns 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_TOKENResponse 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_TOKENResponse 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_TOKENAdds 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_TOKENReplaces 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_TOKENSoft-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
| Field | Required | Description |
|---|---|---|
name | Yes | Computation name |
priceOutput | Yes | Step name that holds the final numeric price |
transactionDimension | Yes | TRANSACTION dimension name (who is billed). Auto-created if missing |
usageType | No | Charge (default) or Payout |
chargeType | No | Picklist name: Usage, Subscription, All, or OTC |
steps | Yes | Ordered steps; each has name, optional label, and formula |
Supported formulas
| Pattern | Example |
|---|---|
| Binary arithmetic | Prompt_Tokens / 1000, A + B, A - B, A * B |
| Unary math | Ceil(Input_Tokens_Converted), Floor(X), Round(X) |
| Rate-card lookup | Price(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_TOKENResponse 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_TOKENResponse 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_TOKENRequest — 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_TOKENThe 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_TOKENResponse 204 — no body.