Skip to content

Create a feature

The features.create operation: POST /api/v1/features in the REST API and the features_create tool in the MCP server.

POST/api/v1/features

Defines a feature of the brand, in the request's mode: something a product grants, such as feature.export (a boolean), seats.max (a limit) or support.level (one of a set of values). Products grant values of it in their entitlements, and customers' entitlements are resolved from what they've bought.

combine says how values from several products merge: or or first for booleans, max, sum or first for limits, first for enums. The key and type never change, and enum values can be added but not removed. A perUnit limit is multiplied by the subscription item's or purchase's quantity.

At a glance

  • REST: POST /api/v1/features
  • MCP tool: features_create
  • Operation ID: features.create
  • Scope: Brand
  • Permission: catalog:write
  • Risk tier: write
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key required
  • Modes: Test and live
  • Authentication: API key with the catalog:write scope
  • Since: M4

Request

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
keystringYesUnique in the brand and mode, e.g. seats.max. Never changes.
namestringYesShown on the pricing table, e.g. Seats.
typeone of boolean, limit, enumYesboolean (on or off), limit (a whole number) or enum (one of a set of values).
enumValuesarray of stringNoEnum features: the allowed values, in display order.
combineone of max, sum, or, firstNoDefault: or for booleans, max for limits, first for enums.
defaultValueboolean or number or stringNoWhat customers without the feature get. Default: false, 0, or the first enum value.
perUnitbooleanNoLimit features only: multiply the value a product grants by the quantity bought or subscribed (e.g. 5 projects per seat). Default false.

Response

201 Created with a JSON object:

FieldTypeDescription
idfeat_… ID
object"feature"
brandIdbrd_… ID
livemodeboolean
keystring
namestring
typeone of boolean, limit, enum
enumValuesarray of string or null
combineone of max, sum, or, first
defaultValueboolean or number or string
perUnitbooleanLimit features only: values are multiplied by the item's or purchase's quantity (spec §36.1).
createdAtdate-time
updatedAtdate-time

Examples

A seat limit, per unit

HTTP
POST /api/v1/features
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "key": "seats.max",
  "name": "Seats",
  "type": "limit",
  "defaultValue": 1,
  "perUnit": true
}

Response (201):

JSON
{
  "id": "feat_01m4tx5nj8emwbyf7y9vcf47y6",
  "object": "feature",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "key": "seats.max",
  "name": "Seats",
  "type": "limit",
  "enumValues": null,
  "combine": "max",
  "defaultValue": 1,
  "perUnit": true,
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-13T12:00:00.000Z"
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400A field is malformed, the combine rule doesn't fit the type, the default isn't a valid value, or perUnit is set on a feature that isn't a limit.Fix the fields listed in details.issues and send the request again.
feature_key_taken409The brand already has a feature with this key in this mode.Choose another key, or update the existing feature.
permission_denied403You can't change this brand's catalog.Ask an organization owner or admin for a role or scope that allows this action.

It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, scope_required, resource_not_found, idempotency_key_required, idempotency_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.