Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 64 additions & 15 deletions api/public-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,24 +104,39 @@ This endpoint retrieves a list of flag values evaluated for a particular user or
The endpoint is a `GET` request to ensure that the request can be completed without a `CORS Preflight` request to reduce latency.
{% endhint %}

The context must be flattened and provided as query parameters. For instance, given the following nested object:

```typescript
{
company: {
id: 42,
},
user: {
id: 99,
},
}
Send the context in one query parameter called `contextJson`. Use `JSON.stringify()` to turn the whole context into JSON text, then `URLSearchParams` to encode it for the URL. Arrays stay as arrays:

```javascript
const context = {
company: { id: "42", entitlements: ["reports", "exports"] },
user: { id: "99", roles: ["admin", "editor"] },
other: { tags: ["beta"] },
};
const query = new URLSearchParams({
publishableKey: "<publishable_key>",
contextJson: JSON.stringify(context),
});
const response = await fetch(`https://front.reflag.com/features/evaluated?${query}`);
const flags = await response.json();
```

It needs to be flattened out into the following form: `context.company.id=42&context.user.id=99` .
The context can include `user`, `company`, and `other` objects. None of these objects is required. User and company IDs are also optional; if provided, they must be strings or numbers, not arrays.

#### Example
Context attributes can hold strings, numbers, true/false values, `null`, or arrays. You can group attributes in one nested object—for example, `user.profile.roles`, targeted with the same dotted path. Deeper object nesting is rejected.

By default, the JSON text can be up to 16,384 bytes before URL encoding. Your HTTP server or proxy may have a lower URL limit.

The API returns a validation error if:

* The JSON is not valid or the context does not follow the rules above.
* You send `contextJson` more than once.
* You send `contextJson` together with `context` or `context.*` parameters.

<pre class="language-http" data-title="Request" data-overflow="wrap"><code class="lang-http"><strong>GET https://front.reflag.com/features/enabled?context.company.id=42&#x26;context.user.id=99&#x26;publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
The older query format still works for single values, such as `context.company.id=42&context.user.id=99`. For arrays, use `contextJson`; do not send separate items as `context.user.roles.0=admin`.

#### Example using the older query format

<pre class="language-http" data-title="Request" data-overflow="wrap"><code class="lang-http"><strong>GET https://front.reflag.com/features/evaluated?context.company.id=42&#x26;context.user.id=99&#x26;publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
</strong></code></pre>

{% code title="Response" %}
Expand All @@ -143,9 +158,35 @@ It needs to be flattened out into the following form: `context.company.id=42&con
Reflag utilizes attributes from the `company` endpoint to identify which features are enabled for specific companies. Ensure all `company` attributes referenced in the `context` are also provided through the `company` endpoint.
{% endhint %}

#### Evaluation errors

Flag results may include `evaluationErrors`:

* `MISSING_CONTEXT_FIELD`: a rule needs a field that was not provided.
* `UNSUPPORTED_ARRAY_OPERATOR`: a rule tried to use an operator that does not work with arrays.

The affected rule does not match, but the API still returns a normal response and other rules can match. Errors while choosing a config value are listed in `config.evaluationErrors`.

```json
{
"evaluationErrors": [
{
"code": "UNSUPPORTED_ARRAY_OPERATOR",
"field": "user.roles",
"operator": "GT",
"message": "Operator GT does not support array-valued context field \"user.roles\"."
}
]
}
```

Older clients can still use `missingContextFields`, which lists missing fields only. Use `evaluationErrors` for new integrations.

See [array attribute operators](../../product-handbook/creating-segments.md#array-attributes) for supported operators and examples.

### `GET /features/enabled`

This endpoint is similar to `features/evaluated` but only includes flags that have been evaluated as `true`.
This endpoint is similar to `features/evaluated` but only includes flags that have been evaluated as `true`. It accepts the same `contextJson` parameter.

### `POST /features/events`

Expand Down Expand Up @@ -294,6 +335,14 @@ Content-Type: application/json
```
{% endcode %}

## Array attributes

You can send arrays in the `attributes` of user, company, and event requests, including bulk requests. Send `"roles": ["admin", "editor"]`, not `"roles": "[\"admin\",\"editor\"]"`.

An update replaces the whole list; sending `[]` clears it. Each array stays one attribute, rather than becoming separate fields such as `roles.0`.

See [array attribute operators](../../product-handbook/creating-segments.md#array-attributes) for matching rules and examples.

## Responses

The API returns a `200` status code for successful calls and a `400` status code for errors, including invalid request bodies.
Expand Down
11 changes: 11 additions & 0 deletions api/public-api/public-api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@
| field | string | <p>Refers to a field of the context object.<br>Example: company.tier</p> |
| values | string\[] | Array of values which will be compared with the value of the context field. Operators SET, NOT\_SET, IS\_TRUE, IS\_FALSE require 0 values, ANY\_OF and NOT\_ANY\_OF support multiple values. All the other operators require exactly one value. |
| operator | enum(`IS`,`IS_NOT`,`ANY_OF`,`NOT_ANY_OF`,`CONTAINS`,`NOT_CONTAINS`","`GT`" ,`LT`,`AFTER`,`BEFORE`,`SET`,`NOT_SET`,`IS_TRUE`,`IS_FALSE`) | Operator for comparison of the context field with provided values. |

When the context field holds an array:

* `IS` matches if the array has just one item equal to the value you chose. `IS_NOT` matches if it has more than one item, is empty, or its only item differs.
* `CONTAINS` matches if the array includes the value you chose. `NOT_CONTAINS` matches if it does not.
* `ANY_OF` matches if the array includes at least one of the values you chose. `NOT_ANY_OF` matches if it includes none.
* `SET` matches arrays with at least one item. `NOT_SET` matches empty arrays.

These checks match whole values and treat uppercase and lowercase letters as different. For example, `["admin"]` does not contain `adm` or `Admin`. Numeric and date operators, plus `IS_TRUE` and `IS_FALSE`, do not work with arrays.

See [array attribute operators](../../product-handbook/creating-segments.md#array-attributes) for examples.
{% endtab %}

{% tab title="Rollout Percentage" %}
Expand Down
10 changes: 10 additions & 0 deletions product-handbook/concepts/filter.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ Reflag supports the following filter types:

This filter can be used to check company attributes against a set of predicates. The attributes include `First seen` and `Last seen`, which are maintained by Reflag. You can use any attribute name that your application sends to Reflag.

### Array attributes

Attributes can hold lists, such as `roles: ["admin", "editor"]`.

* Use `CONTAINS` to check for one value, such as `admin`.
* Use `ANY_OF` to check for any of several values, such as `admin` or `owner`.
* Use `IS` when the list must have just one item, equal to the value you chose.

Array checks match whole values and treat uppercase and lowercase letters as different. See [array attribute operators](../creating-segments.md#array-attributes) for all supported operators and examples.

### Company flag metrics

This filter allows checking company-level flag metrics. These metrics include `Event count`, `First used`, `Last used`, and more.
Expand Down
14 changes: 13 additions & 1 deletion product-handbook/concepts/targeting-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,26 @@ The evaluation context refers simply to a collection of **key** — **value** pa
* Any other [company attributes](company.md#attributes) that might be used by the filters in the rules,
* A collection of "_**other**_" attributes that can be used by the feature access targeting rules.

The exact structure of the data will vary by the SDK in use.
The exact structure of the data will vary by the SDK in use. Custom attributes can also hold arrays, such as `user.roles: ["admin", "editor"]`.

Use `CONTAINS` to check for a role such as `admin`, or `ANY_OF` to check for any of several roles. See [array attribute operators](../creating-segments.md#array-attributes) for examples and the full list of operators.

### Missing context fields

During the evaluation of targeting rules against a context it might happen that context is missing some details that the rules require. In such cases, those rules are discarded from evaluation as it would be unsafe to do otherwise.

Reflag reports these missing context fields using [feature events](feature-events.md). Reflag SDKs will also generate warnings in these cases making it easy to find these situations in your application.

### Checks that do not support arrays

Some operators, such as `GT`, `DATE_AFTER`, and `IS_TRUE`, do not work with arrays. Arrays also cannot be used for percentage rollouts.

If Reflag runs one of these checks on an array, the whole rule does not match. Adding `NOT` does not turn that error into a match. Other rules can still match.

Reflag does not report errors for conditions it skips. For example, if the first condition in an `OR` group matches, Reflag does not check the remaining conditions in that group.

The [evaluation API](../../api/public-api/README.md#evaluation-errors) reports these errors in `evaluationErrors`, with code `UNSUPPORTED_ARRAY_OPERATOR`. Missing fields use `MISSING_CONTEXT_FIELD`. The older `missingContextFields` field is still available but lists missing fields only.

### Next steps

* Learn about [filters](filter.md),
Expand Down
21 changes: 21 additions & 0 deletions product-handbook/creating-segments.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,27 @@ Operators depend on the condition type:
* `In segment`
* `Not in segment`

These attribute operators are also available when you create flag access rules.

#### Array attributes

Attributes can hold arrays such as `roles: ["admin", "editor"]`. Array operators compare whole items and are case-sensitive: `admin` does not match `Admin` or part of a value such as `adm`.

| Operator | Matches an array when |
| --- | --- |
| `Is` | It has exactly one item, equal to the selected value. |
| `Is not` | It is empty, has more than one item, or its only item differs from the selected value. |
| `Contains` | It includes the selected value. |
| `Does not contain` | It does not include the selected value. |
| `Is any of` | It includes at least one selected value. |
| `Is not any of` | It includes none of the selected values. |
| `Has any value` | It has at least one item. |
| `Has no value` | It is empty. |

For example, `roles: ["admin", "editor"]` matches `Contains admin` and `Is any of [admin, owner]`, but it does not match `Is admin`.

Number, date, and boolean operators do not support arrays, and arrays cannot be used for percentage rollouts. If an access rule applies an unsupported operator to an array, that rule does not match.

## Save and reuse the segment

After you save a segment, you can reuse it in flag [access rules](feature-rollouts/feature-targeting-rules.md) and rollout workflows.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Here are examples of access conditions:
* Companies with Company IDs 1 and 2: `Company attribute: Company ID IS ANY OF [1,2]`
* Give access to newly created companies: `Company attribute: createdAt LESS THAN [30] DAYS AGO`
* Give access to users with the manager role at all companies: `User attribute: role IS [manager]`
* Give access to users whose `roles` list includes `manager`: `User attribute: roles contains [manager]`. See [array attribute operators](../creating-segments.md#array-attributes) for more examples.
* Give access to companies in the Pro plan segment: `Segment: In segment ['Pro']`
* Give access to companies in the Beta users’ segment: `Segment: In segment ['Beta users']`
* Give access to companies who already have access to the Huddle flag: `Flag access: Flag [Huddle] is enabled`
Expand Down
Loading