Skip to content

4. Evaluation API

Three calls answer almost every question an application asks, mirroring OpenFeature’s typed getters:

client.isEnabled("sso", ctx) // → boolean
client.getLimit("seats.max", ctx) // → number | UNLIMITED
client.requireWithin("seats.max", current, 1, ctx) // → details, or throws EntitlementLimitExceeded

Each one has a …Details form that returns the full resolution details, the counterpart of OpenFeature’s FlagEvaluationDetails. Four more round out the API: requireEnabled (throws instead of returning false), getEnum, guard (§5), and requiredPlan.

An SDK MUST provide a way to create a client from a provider and a catalog. It MAY also accept a default context, hooks, a clock, and a lock.

The client MUST expose the metadata of its provider (at least name).

Evaluation methods MUST follow their language’s idiom for I/O. An SDK whose providers may perform network I/O SHOULD expose evaluation as asynchronous.

isEnabled(featureCode, context?) → boolean and isEnabledDetails(featureCode, context?) → ResolutionDetails<boolean> MUST evaluate per Requirement 3.2.1. They MUST NOT throw.

requireEnabled(featureCode, context?) → ResolutionDetails<boolean> MUST throw FeatureNotEntitled when isEnabled would return false, and return the details otherwise.

getLimit(privilegeKey, context?) → integer | UNLIMITED and getLimitDetails(privilegeKey, context?) MUST NOT throw. Called on a privilege that is not of type integer, they MUST return 0 with reason ERROR and error code TYPE_MISMATCH.

requireWithin(privilegeKey, current, requested, context?) → ResolutionDetails<Limit> MUST evaluate per §3.3. It MUST return the details when the check passes, and MUST throw EntitlementLimitExceeded (§8.1) when it fails.

getEnum(privilegeKey, context?) → string and getEnumDetails(privilegeKey, context?) MUST NOT throw. Called on a privilege that is not of type enum, they MUST return the empty string with reason ERROR and error code TYPE_MISMATCH.

requiredPlan(privilegeKey, need, context?) → planId | absent MUST return the plan defined by §3.4, where need is true, a {current, requested} pair, or an enum option.

getDetails(privilegeKey, context?) → ResolutionDetails MUST resolve a privilege of any type, with no type expectation, and MUST NOT throw. For a privilege that is not in the catalog, the value MUST be absent (null), with reason ERROR and error code PRIVILEGE_NOT_FOUND.

This is the generic call that admin tools, support consoles, and the conformance suite use.

Resolution details MUST contain:

field type meaning
privilege string the privilege key that was resolved (the gate, for isEnabled)
value boolean · integer · UNLIMITED · string the resolved value
reason Reason why this value (§4.4)
grants list of {id, amount, subjectId?} grants that were added, possibly empty
staleOverrides list of override ids Requirement 3.1.9, possibly empty

Resolution details MUST contain the following fields when they apply, and MUST omit them otherwise: feature (when evaluated through isEnabled), planId, planValue (Requirement 3.1.8), overrideId (when the reason is OVERRIDE, or GRANT on top of an override), requiredPlan (Requirement 3.4.1), errorCode, and errorMessage (when the reason is ERROR).

Resolution details MUST be serializable to JSON, with UNLIMITED encoded per Requirement 1.2.3.

reason MUST be one of:

reason when
PLAN the value is the plan value
OVERRIDE an override replaced the plan value
GRANT grants were added to a finite base (plan, override, or default)
FIXED a fixed provider answered, for example a self-hosted install where everything is on and nothing can be overridden
DEFAULT no plan, or the plan sets no value, so the privilege’s default was used
ERROR resolution failed, so the default was used (Requirement 3.1.11)

errorCode MUST be one of PROVIDER_NOT_READY, PRIVILEGE_NOT_FOUND, FEATURE_NOT_FOUND, TYPE_MISMATCH, INVALID_CONTEXT, or GENERAL.