OpenFeature OFREP Core API
**Required**: Core APIs to implement to support OFREP. *This is the minimum set of APIs required for a flag management system to be OFREP compatible.*
**Required**: Core APIs to implement to support OFREP. *This is the minimum set of APIs required for a flag management system to be OFREP compatible.*
openapi: 3.1.0
info:
version: 0.3.0
title: OpenFeature Remote Evaluation Protocol (OFREP) OFREP Core API
description: "---\nThe **OpenFeature Remote Evaluation Protocol (OFREP)** is an API specification for feature flagging \nthat enables vendor-agnostic communication between applications and flag management systems. \n\nOFREP defines a standard API layer between OpenFeature providers and flag management systems, \nallowing any flag management system to implement the protocol and be compatible with \ncommunity-maintained providers.\n\nFor more information, see the [OFREP documentation](https://openfeature.dev/docs/reference/other-technologies/ofrep/).\n"
contact:
url: https://github.com/open-feature/protocol
license:
identifier: Apache-2.0
name: Apache 2.0
servers:
- url: /
security:
- ApiKeyAuth: []
- BearerAuth: []
tags:
- name: OFREP Core
description: "**Required**: Core APIs to implement to support OFREP. \n*This is the minimum set of APIs required for a flag management system to be OFREP compatible.*\n"
paths:
/ofrep/v1/evaluate/flags/{key}:
post:
tags:
- OFREP Core
summary: Evaluate A Single Feature Flag
description: "Evaluates a single feature flag by its key. This endpoint is used by **server-side providers** \nfor dynamic context evaluation, where each evaluation request includes the evaluation context.\n\nThe endpoint returns the evaluated flag value along with metadata including the evaluation \nreason, variant, and any flag-specific metadata. The flag value can be one of several types: \nboolean, string, integer, float, object, or a code default (indicating the provider should \nuse the code default value).\n\n**Use Case**: Server-side applications where evaluation context may change between requests \nand real-time targeting decisions are required.\n"
operationId: evaluateFlag
parameters:
- name: key
in: path
required: true
description: The unique identifier (key) of the feature flag
schema:
type: string
example: discount-banner
requestBody:
required: true
description: Evaluation request containing the context for flag evaluation
content:
application/json:
schema:
$ref: '#/components/schemas/evaluationRequest'
example:
context:
targetingKey: user-123
email: user@example.com
custom-plan: premium
country: CA
responses:
'200':
description: Successful flag evaluation. Returns the evaluated flag value with metadata.
content:
application/json:
schema:
$ref: '#/components/schemas/serverEvaluationSuccess'
example:
key: discount-banner
value: true
reason: TARGETING_MATCH
variant: enabled
'400':
description: Bad evaluation request. The request is malformed or contains invalid context.
content:
application/json:
schema:
$ref: '#/components/schemas/evaluationFailure'
example:
key: my-flag
errorCode: INVALID_CONTEXT
errorDetails: Context is missing required targetingKey property
'404':
description: Flag not found. The specified flag key does not exist in the flag management system.
content:
application/json:
schema:
$ref: '#/components/schemas/flagNotFound'
example:
key: non-existent-flag
errorCode: FLAG_NOT_FOUND
errorDetails: Flag 'non-existent-flag' was not found
'401':
description: Unauthorized. Authentication credentials are missing, invalid, or expired.
'403':
description: Forbidden. The client does not have permission to access the requested resource.
'429':
description: Too Many Requests. Rate limit has been exceeded.
headers:
Retry-After:
description: "Indicates when to retry the request again. Can be either a date-time string \nor a number of seconds to wait.\n"
schema:
type: string
format: date-time
example: '2024-02-07T12:00:00Z'
'500':
description: Internal Server Error. An unexpected error occurred on the server that prevented flag evaluation.
content:
application/json:
schema:
$ref: '#/components/schemas/generalErrorResponse'
example:
errorDetails: An internal server error occurred while processing the request
/ofrep/v1/evaluate/flags:
post:
tags:
- OFREP Core
summary: Bulk Evaluate All Feature Flags
description: "Evaluates all feature flags in a single request using a static context. This endpoint is \nused by **client-side providers** for static context evaluation, where all flags are evaluated \nonce and then cached locally for subsequent use.\n\nThe endpoint returns an array of all flag evaluations, where each flag can be either a \nsuccessful evaluation or an evaluation failure. The response includes an ETag header for \ncache validation, allowing clients to use the `If-None-Match` header to avoid unnecessary \nre-evaluation when flags haven't changed.\n"
operationId: evaluateFlagsBulk
parameters:
- in: header
name: If-None-Match
description: "Optional ETag value from a previous bulk evaluation response. If provided and the \nETag matches the current flag set, the server will return a 304 Not Modified response, \nindicating that flags haven't changed since the last evaluation.\n"
schema:
type: string
required: false
example: abc123xyz
- $ref: '#/components/parameters/flagConfigEtag'
- $ref: '#/components/parameters/flagConfigLastModified'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/bulkEvaluationRequest'
example:
context:
targetingKey: user-456
email: user@example.com
plan: free
country: CA
responses:
'200':
description: Successful bulk evaluation.
headers:
ETag:
schema:
type: string
description: "Entity tag (ETag) representing the current state of all flags. Clients should \ninclude this value in subsequent requests using the `If-None-Match` header for \ncache validation.\n"
example: abc123xyz
content:
application/json:
schema:
$ref: '#/components/schemas/bulkEvaluationSuccess'
example:
flags:
- key: discount-banner
value: true
reason: TARGETING_MATCH
variant: enabled
- key: theme-color
value: blue
reason: STATIC
variant: default
- key: non-existent-flag
errorCode: FLAG_NOT_FOUND
errorDetails: Flag 'non-existent-flag' was not found
eventStreams:
- type: sse
url: https://sse.example.com/event-stream?channels=env_abc123_v1
inactivityDelaySec: 120
metadata:
version: v12
'304':
description: 'Not Modified. The flags haven''t changed since the last evaluation (ETag matches). No response body is returned.
'
'400':
description: Bad evaluation request. The request is malformed or contains invalid context.
content:
application/json:
schema:
$ref: '#/components/schemas/bulkEvaluationFailure'
example:
errorCode: INVALID_CONTEXT
errorDetails: Context is missing required targetingKey property
'401':
description: Unauthorized. Authentication credentials are missing, invalid, or expired.
'403':
description: Forbidden. The client does not have permission to access the requested resource.
'429':
description: Too Many Requests. Rate limit has been exceeded.
headers:
Retry-After:
description: "Indicates when to retry the request again. Can be either a date-time string \nor a number of seconds to wait.\n"
schema:
oneOf:
- type: string
format: date-time
- type: integer
description: Number of seconds to wait before retrying
example: '2024-02-07T12:00:00Z'
'500':
description: Internal server error. An unexpected error occurred on the server that prevented flag evaluation.
content:
application/json:
schema:
$ref: '#/components/schemas/generalErrorResponse'
example:
errorDetails: An internal server error occurred while processing the request
components:
parameters:
flagConfigEtag:
in: query
name: flagConfigEtag
description: 'Optional ETag metadata provided by an event stream for change-triggered
re-fetches (see ADR-0008). This is not a standard HTTP conditional request
header; it is metadata for server-side cache validation and freshness
checks. It should only be included when the request is directly triggered
by a received change notification event.
'
schema:
type: string
required: false
example: 550e8400-e29b-41d4-a716-446655440000
flagConfigLastModified:
in: query
name: flagConfigLastModified
description: 'Optional last-modified metadata provided by an event stream for
change-triggered re-fetches (see ADR-0008). Supports Unix timestamp in
seconds (recommended) or an ISO 8601 date-time string, and is
transported as query metadata rather than `If-Modified-Since`. It should
only be included when the request is directly triggered by a received
change notification event.
'
schema:
oneOf:
- type: integer
minimum: 0
- type: string
format: date-time
required: false
examples:
epochSeconds:
value: 1771622898
isoDate:
value: '2026-02-20T21:28:18Z'
schemas:
bulkEvaluationFailure:
description: "Failure response for bulk evaluation. Returned when the entire bulk evaluation request \nfails (e.g., invalid context, parse errors). Individual flag failures within a successful \nbulk evaluation are represented as evaluationFailure items in the flags array.\n"
type: object
properties:
errorCode:
type: string
description: "An error code specific to the bulk evaluation error. See \nhttps://openfeature.dev/specification/types#error-code for error code definitions.\n"
example: INVALID_CONTEXT
errorDetails:
type: string
description: Optional error details description for logging or debugging purposes
example: Context is missing required targetingKey property
required:
- errorCode
evaluationFailure:
description: "Feature flag evaluation failure response. Returned when a feature flag evaluation fails, such as when \nthe context is invalid, required targeting keys are missing, or parsing errors occur. \n"
type: object
properties:
key:
$ref: '#/components/schemas/key'
errorCode:
type: string
description: "OpenFeature compatible error code indicating the type of error. See \nhttps://openfeature.dev/specification/types#error-code for error code definitions.\n"
enum:
- PARSE_ERROR
- TARGETING_KEY_MISSING
- INVALID_CONTEXT
- GENERAL
errorDetails:
$ref: '#/components/schemas/errorDetails'
metadata:
allOf:
- $ref: '#/components/schemas/metadata'
- $ref: '#/components/schemas/flagMetadataDescription'
- $ref: '#/components/schemas/flagMetadataExamples'
required:
- key
- errorCode
bulkEvaluationSuccess:
description: "Success response for bulk flag evaluation. Contains an array of flag evaluations, \nwhere each item can be either a successful evaluation or an evaluation failure. \nThis allows partial success scenarios where some flags may fail while others succeed.\n"
type: object
required:
- flags
properties:
flags:
type: array
description: Array of flag evaluations. Each evaluation can be a success or failure.
items:
oneOf:
- $ref: '#/components/schemas/evaluationSuccess'
- $ref: '#/components/schemas/evaluationFailure'
metadata:
$ref: '#/components/schemas/metadata'
description: 'Arbitrary metadata for the flag set, useful for telemetry and documentary purposes.
'
eventStreams:
type: array
description: 'Optional array of real-time change notification connections. When present,
the provider should connect to any entries with a known type and re-fetch
flag evaluations when notified of changes. If not present, the provider
should continue using polling for change detection. Entries with unknown
types must be ignored for forward compatibility.
'
items:
$ref: '#/components/schemas/eventStream'
integerFlag:
description: An integer typed flag value.
type: object
properties:
value:
type: integer
required:
- value
flagMetadataExamples:
description: Example metadata structure for flags
example:
team: ecommerce
businessPurpose: experiment
owner: product-team
evaluationRequest:
description: "Request body for single feature flag evaluation. Contains the evaluation context that will be \nused to evaluate the feature flag.\n"
type: object
required:
- context
properties:
context:
$ref: '#/components/schemas/context'
codeDefaultFlag:
description: "A flag evaluation that defers to the code default value. When a flag evaluation returns \nthis type, it indicates that the provider should use the default value specified in the \napplication code rather than a value from the flag management system.\n\n**Note**: This schema has no `value` property. The provider must use the code default \nvalue when processing this response.\n"
type: object
properties: {}
serverEvaluationSuccess:
allOf:
- $ref: '#/components/schemas/evaluationSuccess'
metadata:
type: object
description: "Arbitrary metadata object that can contain any additional information about flags or \nflag sets. This metadata is useful for debugging and telemetry purposes.\n"
additionalProperties:
oneOf:
- type: boolean
- type: string
- type: number
floatFlag:
description: A float typed flag value.
type: object
properties:
value:
type: number
format: float
required:
- value
generalErrorResponse:
description: "General error response for unexpected server errors (500 status). Used when the \nserver encounters an internal error that prevents flag evaluation.\n"
type: object
properties:
errorDetails:
$ref: '#/components/schemas/errorDetails'
key:
type: string
description: "The unique identifier (key) of the feature flag. This is used to reference a specific \nflag in the flag management system.\n"
example: discount-banner
context:
type: object
description: "Evaluation context containing information used to evaluate feature flags. The context \nincludes a `targetingKey` (required) along with additional properties such as \nuser attributes, session data, or request metadata that can be used for targeting rules.\n"
required:
- targetingKey
properties:
targetingKey:
type: string
additionalProperties: true
example:
targetingKey: user-123
email: user@example.com
plan: premium
country: CA
flagMetadataDescription:
description: 'Arbitrary metadata for the flag, useful for telemetry and documentary purposes.
'
stringFlag:
description: A string typed flag value.
type: object
properties:
value:
type: string
required:
- value
flagNotFound:
description: "Feature flag not found response. Returned when a requested feature flag key does not exist in the \nflag management system. This can be an expected response in certain flag management systems. \nThis is distinct from evaluation failures, which occur when a flag exists but cannot be evaluated.\n"
type: object
properties:
key:
$ref: '#/components/schemas/key'
errorCode:
type: string
description: Error code indicating the flag was not found
enum:
- FLAG_NOT_FOUND
errorDetails:
$ref: '#/components/schemas/errorDetails'
metadata:
allOf:
- $ref: '#/components/schemas/metadata'
- $ref: '#/components/schemas/flagMetadataDescription'
- $ref: '#/components/schemas/flagMetadataExamples'
required:
- key
- errorCode
bulkEvaluationRequest:
description: "Request body for bulk flag evaluation. Contains a static context that will be used \nto evaluate all flags.\n"
type: object
required:
- context
properties:
context:
$ref: '#/components/schemas/context'
eventStream:
description: 'A real-time change notification connection endpoint. The `type` field
identifies the push mechanism; currently only `sse` is defined. Providers
must ignore entries with unknown types for forward compatibility.
Exactly one of `url` or `endpoint` must be provided.
'
type: object
required:
- type
oneOf:
- required:
- url
not:
required:
- endpoint
- required:
- endpoint
not:
required:
- url
properties:
type:
type: string
description: 'The connection type identifying the push mechanism to use.
Currently only `sse` is defined. Providers must ignore entries
with unknown types for forward compatibility.
'
example: sse
url:
type: string
format: uri
description: 'The endpoint URL the client should connect to for real-time
flag change notifications. This is the default representation and
is opaque to the provider. The URL may include authentication tokens,
channel identifiers, or other query parameters as needed by the
vendor''s infrastructure. Implementations must treat this value as
sensitive and must not log or persist the full URL including its
query string.
'
example: https://sse.example.com/event-stream?channels=env_abc123_v1
endpoint:
$ref: '#/components/schemas/eventStreamEndpoint'
inactivityDelaySec:
type: integer
minimum: 1
default: 120
description: 'Number of seconds of client inactivity (e.g., browser tab hidden,
mobile app backgrounded) after which the connection should be closed
to conserve resources. The client must reconnect and perform a full
unconditional re-fetch when activity resumes. When determining the
effective inactivity timeout, providers should use a client-side
override if configured; otherwise use this value when present;
otherwise default to 120 seconds.
'
example: 120
evaluationSuccess:
description: "Successful feature flag evaluation response. The value property is present \nfor all flag types except `codeDefaultFlag`, which indicates the provider should use the \ncode default value.\n"
type: object
required:
- key
- reason
allOf:
- properties:
key:
$ref: '#/components/schemas/key'
reason:
type: string
description: "An OpenFeature reason code indicating why the flag was evaluated to this value. \nSee https://openfeature.dev/specification/types/#resolution-reason for reason code definitions.\n"
enum:
- STATIC
- TARGETING_MATCH
- SPLIT
- DISABLED
- UNKNOWN
variant:
type: string
description: "Variant identifier for the evaluated feature flag value. Represents a specific variation \nor configuration of the feature flag.\n"
metadata:
allOf:
- $ref: '#/components/schemas/metadata'
- $ref: '#/components/schemas/flagMetadataDescription'
- $ref: '#/components/schemas/flagMetadataExamples'
- oneOf:
- $ref: '#/components/schemas/booleanFlag'
- $ref: '#/components/schemas/stringFlag'
- $ref: '#/components/schemas/integerFlag'
- $ref: '#/components/schemas/floatFlag'
- $ref: '#/components/schemas/objectFlag'
- $ref: '#/components/schemas/codeDefaultFlag'
eventStreamEndpoint:
type: object
required:
- requestUri
description: 'Structured endpoint components for deployments that need to override
the origin cleanly while preserving the request target. When present,
providers construct the connection URL as `origin + requestUri`. If
`origin` is absent, providers should use their configured OFREP base
URL origin.
'
properties:
origin:
type: string
format: uri
description: 'The scheme + host + optional port portion of the endpoint URL.
If absent, providers should use their configured OFREP base URL origin.
'
example: https://sse.example.com
requestUri:
type: string
pattern: ^/
description: 'The path + query portion of the endpoint URL. Must start with `/`.
'
example: /event-stream?channels=env_abc123_v1
errorDetails:
type: string
description: "A human-readable error description providing additional context about the evaluation \nfailure. Useful for logging, debugging, and monitoring purposes.\n"
booleanFlag:
description: A boolean typed flag value. Used for simple on/off feature flags.
type: object
properties:
value:
type: boolean
required:
- value
objectFlag:
description: An object typed flag value.
type: object
properties:
value:
type: object
additionalProperties: true
required:
- value
securitySchemes:
BearerAuth:
description: "Optional Bearer token authentication. If supported by the flag management system, \nclients can authenticate using a Bearer token in the `Authorization` header following \nthe format: `Authorization: Bearer <token>`.\n"
type: http
scheme: bearer
bearerFormat: JWT
ApiKeyAuth:
description: "Optional API key authentication. If supported by the flag management system, clients \ncan authenticate by providing an API key in the `X-API-Key` header.\n"
type: apiKey
in: header
name: X-API-Key