Getting started

Openflip API

Every request authenticates with a Bearer API key from your dashboard. Base URL: https://openflip.in/api/public/v1.

header
Authorization: Bearer ofk_live_...

AI Bots

Register bots via the dashboard or the REST API, then chat to them from any client.

Deploy a bot

POST /v1/bots
curl -X POST https://your-app/api/public/v1/bots \
  -H "Authorization: Bearer ofk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support bot",
    "description": "Answers billing questions",
    "system_prompt": "You are a concise Openflip support agent.",
    "model": "google/gemini-3-flash-preview",
    "status": "active"
  }'
response
{ "bot": { "id": "…", "name": "Support bot", "status": "active", … } }

List / update / delete

rest
GET    /v1/bots               → { bots: [...] }
GET    /v1/bots/{botId}       → { bot: {...} }
PATCH  /v1/bots/{botId}       → update name / system_prompt / model / status
DELETE /v1/bots/{botId}       → 204

Chat with a bot

POST /v1/bots/{botId}/chat
curl -X POST https://your-app/api/public/v1/bots/BOT_ID/chat \
  -H "Authorization: Bearer ofk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      { "role": "user", "content": "How do I refund an order?" }
    ],
    "external_user_id": "user-42"
  }'
response
{ "reply": "You can refund an order from …" }

API keys

Manage keys from the app dashboard: create, rotate (revokes the old value and returns a new one under the same name), or revoke. Full key values are shown once at creation or rotation — store them in your secret manager immediately.

header
Authorization: Bearer ofk_live_XXXXXXXXXXXXXXXX

Push notifications

Subscribe browsers, then send an AI-generated notification with a single call.

1. Get VAPID public key

GET /v1/vapid-public-key
fetch("/api/public/v1/vapid-public-key")
  .then(r => r.json())
  .then(({ publicKey }) => publicKey)

2. Subscribe the browser

js
const reg = await navigator.serviceWorker.register("/sw.js");
const sub = await reg.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: publicKey, // Uint8Array
});

await fetch("https://your-app/api/public/v1/push/subscribe", {
  method: "POST",
  headers: {
    "Authorization": "Bearer ofk_live_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    ...sub.toJSON(),
    external_user_id: currentUser.id,
  }),
});

3. Send an AI-generated notification

POST /v1/notifications
curl -X POST https://your-app/api/public/v1/notifications \
  -H "Authorization: Bearer ofk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Alex sent you a new offer of $42",
    "tone": "friendly",
    "audience": ["user-42"],
    "url": "https://myapp.com/inbox"
  }'

Omit audience or pass "all" to broadcast. Pass explicit title/body to skip AI generation.

Sign in with Openflip

Standard OAuth 2.0 + OIDC. Register a client via dynamic client registration or in your app settings, then run a normal authorization code flow.

discovery
GET /.well-known/oauth-authorization-server

Authorization code flow

1. redirect user
GET https://your-app/oauth/authorize
    ?response_type=code
    &client_id=YOUR_CLIENT_ID
    &redirect_uri=https://yourapp.com/callback
    &scope=openid%20email%20profile
    &state=RANDOM
    &code_challenge=BASE64URL(SHA256(verifier))
    &code_challenge_method=S256
2. exchange code
curl -X POST https://your-app/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTH_CODE" \
  -d "redirect_uri=https://yourapp.com/callback" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "code_verifier=VERIFIER"
3. fetch identity
curl https://your-app/oauth/userinfo \
  -H "Authorization: Bearer ACCESS_TOKEN"
# { "sub": "…", "email": "user@example.com", "name": "…" }

Consent screen: /.lovable/oauth/consent. Default scopes: openid email profile.