Herald
OpenapiBilling

Create_entitlement_mapping

Generic over provider (IAP, Stripe, Creem). Required permission: `billing.manage`; distribution-rule fields additionally require `points.manage` (mirrors the batch update permission model). A duplicate `(realm, provider, product, price)` row violates `uq_pem_realm_provider_product_price` and surfaces as HTTP 409.

POST
/api/bill/{realmId}/entitlement-mappings

Generic over provider (IAP, Stripe, Creem). Required permission: billing.manage; distribution-rule fields additionally require points.manage (mirrors the batch update permission model). A duplicate (realm, provider, product, price) row violates uq_pem_realm_provider_product_price and surfaces as HTTP 409.

Authorization

bearer_auth
AuthorizationBearer <token>

In: header

Path Parameters

realmId*string

Realm ID

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

billingPeriod?|

Required when billing_type == "recurring"; must be empty for "non_renewing" (mutually exclusive billing semantics).

billingType*string

"recurring" / "one_time" / "non_renewing".

currency?|

ISO 4217 currency code for the manual price — required for WeChat, rejected for every other provider.

enabled?boolean
entitlementKey*string
externalPriceId?|

Stripe Price ID for Stripe; None for IAP / Creem.

externalProductId*string
grantedRoleIds?array<>

Roles auto-granted on payment success.

paymentProvider*string

"apple" / "google" / "stripe" / "creem" / "wechat".

pointRules?array<>

Initial points distribution rules owned by the new mapping (upsert set; empty / omitted is a valid "no points grant" mapping). Each rule is validated against the mapping's billing type before persistence. Non-empty triggers the points.manage credit-field permission gate.

price?|

Manual price in minor units (e.g. fen for CNY) — required for WeChat (no hosted catalog to sync from; the price drives the WeChat order amount) and rejected for every other provider.

Formatint64
serviceDurationDays?|

Non-renewing service-period length (days). Required (>= 1) when

Formatint64

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/api/bill/string/entitlement-mappings" \  -H "Content-Type: application/json" \  -d '{    "billingType": "string",    "entitlementKey": "string",    "externalProductId": "string",    "paymentProvider": "string"  }'
{  "billingPeriod": "string",  "billingType": "string",  "createdAt": "string",  "enabled": true,  "entitlementKey": "string",  "externalPriceId": "string",  "externalProductId": "string",  "grantedRoleIds": [    "d7da45c3-cf14-4d32-83d9-df3496b53a96"  ],  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "paymentProvider": "string",  "pointRules": [    {      "bucketId": "1980377d-7926-47e0-9e64-a9d0c746404d",      "displayOrder": 0,      "enabled": true,      "grantMode": "string",      "grantPeriodType": "string",      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",      "pointsAmount": 0,      "quotaWindows": [        {          "key": "string",          "limit": 0,          "windowSeconds": 0        }      ],      "triggerSources": [        "string"      ],      "validityDays": 0    }  ],  "providerProductInfo": null,  "serviceDurationDays": 0,  "syncedAt": "string",  "updatedAt": "string"}
{  "code": "string",  "field": "string",  "message": "string",  "ruleId": "70af3071-65d9-4ec3-b3cb-5283e8d55dac"}
{  "code": "string",  "details": null,  "message": "string",  "requestId": "string",  "status": 0}
{  "code": "string",  "details": null,  "message": "string",  "requestId": "string",  "status": 0}
{  "code": "string",  "field": "string",  "message": "string",  "ruleId": "70af3071-65d9-4ec3-b3cb-5283e8d55dac"}
{  "code": "string",  "details": null,  "message": "string",  "requestId": "string",  "status": 0}