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.*

OpenAPI Specification

openfeature-ofrep-core-api-openapi.yml Raw ↑
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