Skip to main content

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

FieldTypeDescription
appIdstringApp identifier
envstringEnvironment name
versionnumberConfig version number
doc.flagsobjectFlag key-value pairs
doc.overridesobjectReserved for future use
doc.rulesobjectReserved for future use
ttlSecondsnumberRecommended cache TTL

Flag Types

Each flag has a type and value:
TypeExample Value
booltrue or false
string"light" or "dark"
number100 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:
FlagClient EnabledReturned 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:
ETag: "v42"
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>
}

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