Skip to content

Commit 29e0fc1

Browse files
committed
new: REST API SDK
1 parent 2f4574f commit 29e0fc1

66 files changed

Lines changed: 6327 additions & 27 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.local.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"WebFetch(domain:raw.githubusercontent.com)",
5+
"Bash(yarn install)",
6+
"Bash(yarn generate)",
7+
"WebFetch(domain:heyapi.dev)",
8+
"Bash(yarn build)",
9+
"Bash(yarn tsc:*)",
10+
"Bash(yarn format:*)",
11+
"Bash(yarn lint)",
12+
"Bash(yarn prettier)",
13+
"Bash(yarn prettier:*)",
14+
"Bash(NODE_TLS_REJECT_UNAUTHORIZED=0 yarn build:*)"
15+
]
16+
}
17+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"license": "MIT",
66
"workspaces": [
77
"packages/*",
8+
"packages/rest-api-sdk/examples/*",
89
"packages/react-sdk/dev/*",
910
"packages/openfeature-browser-provider/example"
1011
],
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dist/
2+
src/generated/

packages/rest-api-sdk/README.md

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
# @reflag/rest-api-sdk
2+
3+
Type-safe REST API client for the Reflag API.
4+
5+
## Installation
6+
7+
```bash
8+
npm install @reflag/rest-api-sdk
9+
# or
10+
yarn add @reflag/rest-api-sdk
11+
```
12+
13+
## Quick Start
14+
15+
```typescript
16+
import { Api } from "@reflag/rest-api-sdk";
17+
18+
const api = new Api({
19+
accessToken: process.env.REFLAG_API_KEY,
20+
});
21+
22+
const apps = await api.listApps();
23+
console.log(apps.data);
24+
```
25+
26+
```typescript
27+
import { createAppClient } from "@reflag/rest-api-sdk";
28+
29+
// App-scoped client keeps appId out of each call.
30+
const appApi = createAppClient("app-123", {
31+
accessToken: process.env.REFLAG_API_KEY,
32+
});
33+
34+
const environments = await appApi.listEnvironments({
35+
sortBy: "order",
36+
sortOrder: "asc",
37+
});
38+
console.log(environments.data);
39+
```
40+
41+
## Authentication
42+
43+
All API requests require a Bearer token. Get your API key from the Reflag dashboard.
44+
45+
```typescript
46+
import { Api } from "@reflag/rest-api-sdk";
47+
48+
const api = new Api({
49+
accessToken: "your-api-key",
50+
});
51+
```
52+
53+
## API Methods
54+
55+
### Applications
56+
57+
```typescript
58+
import { Api } from "@reflag/rest-api-sdk";
59+
60+
const api = new Api();
61+
62+
// List all apps
63+
const apps = await api.listApps();
64+
65+
// Filter by organization
66+
const appsByOrg = await api.listApps({ orgId: "org-123" });
67+
68+
// Get a single app
69+
const app = await api.getApp({
70+
appId: "app-123",
71+
});
72+
```
73+
74+
### Environments
75+
76+
```typescript
77+
import { createAppClient } from "@reflag/rest-api-sdk";
78+
79+
const appApi = createAppClient("app-123");
80+
81+
// App-scoped client (appId is implicit)
82+
const environments = await appApi.listEnvironments({
83+
sortBy: "order",
84+
sortOrder: "asc",
85+
});
86+
87+
const environment = await appApi.getEnvironment({
88+
envId: "env-456",
89+
});
90+
```
91+
92+
You can also pass `appId` with every call instead of using `createAppClient`:
93+
94+
```typescript
95+
const environments = await api.listEnvironments({
96+
appId: "app-123",
97+
sortBy: "order",
98+
sortOrder: "asc",
99+
});
100+
101+
const environment = await api.getEnvironment({
102+
appId: "app-123",
103+
envId: "env-456",
104+
});
105+
```
106+
107+
### Flags
108+
109+
```typescript
110+
const flags = await api.listFlags({ appId: "app-123" });
111+
112+
const targeting = await api.getFlagTargeting({
113+
appId: "app-123",
114+
flagKey: "my-feature-flag",
115+
envId: "env-456",
116+
});
117+
118+
const updated = await api.updateBulkFlagSpecificTargets({
119+
appId: "app-123",
120+
envId: "env-456",
121+
bulkUpdateFlagSpecificTargetsSchema: {
122+
updates: [
123+
{ flagKey: "new-feature", value: true, companyId: "company-1" },
124+
{ flagKey: "new-feature", value: true, userId: "user-1" },
125+
{ flagKey: "old-feature", value: null, companyId: "company-1" },
126+
],
127+
notifications: true,
128+
changeDescription: "Enabling new feature for beta testers",
129+
},
130+
});
131+
```
132+
133+
### Company Flags
134+
135+
```typescript
136+
const companyFlags = await api.getCompanyFlags({
137+
appId: "app-123",
138+
companyId: "company-1",
139+
envId: "env-456",
140+
});
141+
142+
const updatedCompanyFlags = await api.updateCompanyFlags({
143+
appId: "app-123",
144+
companyId: "company-1",
145+
envId: "env-456",
146+
updateEntityFlagsBody: {
147+
flags: {
148+
"feature-flag": true,
149+
"another-flag": false,
150+
},
151+
},
152+
});
153+
```
154+
155+
### User Flags
156+
157+
```typescript
158+
const userFlags = await api.getUserFlags({
159+
appId: "app-123",
160+
userId: "user-1",
161+
envId: "env-456",
162+
});
163+
164+
const updatedUserFlags = await api.updateUserFlags({
165+
appId: "app-123",
166+
userId: "user-1",
167+
envId: "env-456",
168+
updateEntityFlagsBody: {
169+
flags: {
170+
"feature-flag": true,
171+
"beta-feature": true,
172+
},
173+
},
174+
});
175+
```
176+
177+
## Error Handling
178+
179+
Methods throw on non-2xx responses. Catch errors and inspect the response when needed.
180+
181+
```typescript
182+
try {
183+
const apps = await api.listApps();
184+
console.log(apps.data);
185+
} catch (error) {
186+
if (error instanceof Error) {
187+
console.error("Request failed", error.message);
188+
}
189+
throw error;
190+
}
191+
```
192+
193+
## Types
194+
195+
All generated types are exported for use in your application:
196+
197+
```typescript
198+
import type {
199+
AppHeader,
200+
EnvironmentHeader,
201+
EnvironmentDetails,
202+
FlagHeader,
203+
FlagTargeting,
204+
ErrorResponse,
205+
} from "@reflag/rest-api-sdk";
206+
```
207+
208+
## Regenerating the SDK
209+
210+
To regenerate the SDK:
211+
212+
```bash
213+
yarn generate
214+
```
215+
216+
The schema source lives at `https://app.reflag.com/openapi.json`.
217+
218+
## License
219+
220+
MIT
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const base = require("@reflag/eslint-config");
2+
3+
module.exports = [
4+
...base,
5+
{
6+
ignores: ["dist/", "src/generated/", "examples/**", "**/.next/**"],
7+
},
8+
];
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Customer Admin Panel
2+
3+
Small Next.js (App Router) app that uses `@reflag/rest-api-sdk` with server actions to view and toggle flags for users and companies.
4+
5+
## Setup
6+
7+
Create a `.env.local` file in this folder with:
8+
9+
```
10+
REFLAG_API_KEY=your-api-key
11+
# Optional
12+
REFLAG_BASE_URL=https://app.reflag.com/api
13+
```
14+
15+
## Run
16+
17+
```bash
18+
yarn dev
19+
```
20+
21+
Visit:
22+
- http://localhost:3000/flags/user
23+
- http://localhost:3000/flags/company

0 commit comments

Comments
 (0)