Public Config Endpoint
The /public-config endpoint returns filtered flag configs for client-side applications (browsers, mobile apps).
Endpoint
GET /api/v1/public-config
Authentication
Use a public client key (pub_*) in the Authorization header:
curl https://superflag.sh/api/v1/public-config \
-H "Authorization: Bearer pub_prod_..."
Only use public keys (pub_*) in client-side code. Never use SDK keys (sdk_*) in browsers or mobile apps.
Response
Success (200 OK)
{
"appId": "app_abc123",
"env": "production",
"version": 42,
"doc": {
"flags": {
"dark-mode": {
"type": "bool",
"value": true
},
"api-url": {
"type": "string",
"value": "https://api.example.com"
},
"max-items": {
"type": "number",
"value": 100
},
"theme-config": {
"type": "json",
"value": {
"primaryColor": "#3B82F6",
"borderRadius": 8
}
}
},
"overrides": {},
"rules": {}
},
"ttlSeconds": 60
}
Not Modified (304)
If you provide an If-None-Match header with the current ETag, and the config hasn’t changed:
curl https://superflag.sh/api/v1/public-config \
-H "Authorization: Bearer pub_..." \
-H "If-None-Match: \"v42\""
# Returns 304 Not Modified with no body
Unauthorized (401)
Invalid or missing key:
{
"error": "Invalid or unauthorized client key"
}
Rate Limited (429)
Monthly quota exceeded:
{
"error": "Monthly quota exceeded"
}
Response Fields
| Field | Type | Description |
|---|
appId | string | App identifier |
env | string | Environment name |
version | number | Config version number |
doc.flags | object | Flag key-value pairs |
doc.overrides | object | Reserved for future use |
doc.rules | object | Reserved for future use |
ttlSeconds | number | Recommended cache TTL |
Flag Types
Each flag has a type and value:
| Type | Example Value |
|---|
bool | true or false |
string | "light" or "dark" |
number | 100 or 3.14 |
json | {"color": "#3B82F6"} |
Client Filtering
Only flags with clientEnabled: true are returned to public keys. This prevents accidentally exposing internal/server-only flags to clients.
Example:
| Flag | Client Enabled | Returned to pub_*? |
|---|
dark-mode | ✅ Yes | ✅ Yes |
api-secret | ❌ No | ❌ No |
internal-debug | ❌ No | ❌ No |
ETag Caching
The response includes an ETag header based on the version:
On subsequent requests, send the ETag in If-None-Match:
curl https://superflag.sh/api/v1/public-config \
-H "Authorization: Bearer pub_..." \
-H "If-None-Match: \"v42\""
If the config hasn’t changed, you’ll get a 304 Not Modified response with no body, saving bandwidth.
Examples
Fetch Config (JavaScript)
const response = await fetch('https://superflag.sh/api/v1/public-config', {
headers: {
'Authorization': `Bearer ${clientKey}`
}
})
const data = await response.json()
console.log(data.doc.flags)
With ETag (JavaScript)
let etag = localStorage.getItem('superflag-etag')
const response = await fetch('https://superflag.sh/api/v1/public-config', {
headers: {
'Authorization': `Bearer ${clientKey}`,
...(etag && { 'If-None-Match': etag })
}
})
if (response.status === 304) {
// Use cached config
const cached = JSON.parse(localStorage.getItem('superflag-config'))
return cached
}
const data = await response.json()
// Save new config and ETag
localStorage.setItem('superflag-config', JSON.stringify(data))
localStorage.setItem('superflag-etag', response.headers.get('ETag'))
return data
Curl
# Basic request
curl https://superflag.sh/api/v1/public-config \
-H "Authorization: Bearer pub_prod_..."
# With ETag
curl https://superflag.sh/api/v1/public-config \
-H "Authorization: Bearer pub_prod_..." \
-H "If-None-Match: \"v42\"" \
-v # Show 304 status
SDK Usage
The official SDKs handle this endpoint automatically with ETag caching:
import { SuperflagProvider, useFlag } from '@superflag-sh/react'
function App() {
return (
<SuperflagProvider clientKey="pub_prod_...">
<MyComponent />
</SuperflagProvider>
)
}
function MyComponent() {
const darkMode = useFlag('dark-mode', false)
return <div>{darkMode ? 'Dark' : 'Light'}</div>
}
import { SuperflagProvider, useFlag } from '@superflag-sh/react-native'
import { Text } from 'react-native'
export default function App() {
return (
<SuperflagProvider clientKey="pub_prod_...">
<MyScreen />
</SuperflagProvider>
)
}
function MyScreen() {
const darkMode = useFlag('dark-mode', false)
return <Text>{darkMode ? 'Dark' : 'Light'}</Text>
}
Error Handling
Always handle potential errors:
try {
const response = await fetch('https://superflag.sh/api/v1/public-config', {
headers: { 'Authorization': `Bearer ${clientKey}` }
})
if (response.status === 401) {
console.error('Invalid client key')
return fallbackConfig
}
if (response.status === 429) {
console.warn('Rate limited - using cached config')
return cachedConfig
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return await response.json()
} catch (error) {
console.error('Failed to fetch config:', error)
return fallbackConfig
}
Next Steps