Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/secure-flows-com:secure-flows-com-applications-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: secureFlows Management Applications API
version: 1.8.0
description: 'REST API for **workspace owners/admins** and **end-user flows** (login, invites, anonymous, self-service).
Base path: **`/api/v1`**.
### Workspace access policies
Each workspace has two independent toggles (see **`Workspace`**, **`WorkspaceCreateRequest`**, **`WorkspaceUpdateRequest`**):
| Field | Default | Controls |
|-------|---------|----------|
| **`acceptAnonimous`** | `true` | Whether anonymous Firebase users may join via **`POST /users/anonymous`** or session create without a prior invite |
| **`enableSelfService`** | `true` | Whether end users may use the self-service dashboard (**`GET /users/memberships`**, **`POST /users/login`** as `USER`/`ANONIMOUS`, **`GET /sessions/my`**, **`POST /sessions/revoke/{sessionId}`**) |
When **`enableSelfService`** is `false`, those self-service routes return **403** for end-user roles; **`ADMIN`** and **`OWNER`** console login via **`POST /users/login`** is unchanged.
### Error responses
Failures return JSON **`{"status": , "error": ""}`** unless noted otherwise.
Billing plan limit failures use **HTTP 429** with stable **`code`** values
**`BILLING_SESSION_LIMIT`** or **`BILLING_PAYLOAD_LIMIT`** (see session create / payload write paths).
### Firebase email (console, audit, integrated app UI)
Verified Firebase ID tokens may include an **`email`** claim. The server **best-effort** persists it on
the workspace user row when missing — on **`POST /users/login`**, **`GET /users`** (current page),
**`GET /users/{id}`**, session create/get-or-create/renew, and **`GET /auth/callback`** (create/renew).
This does not change authentication; it helps **`GET /users`**, **`GET /audit/events`**, and
**`GET /audit/api-access`** return emails instead of Firebase UIDs where possible. Clients do not
send email in request bodies.
**Integrated apps:** after sign-in, call **`GET /sessions/identity`** with the session token to display
the signed-in user''s email in the app UI (e.g. next to **Sign out**) and to get a stable `userId` for
your own backend to correlate external events against. Response: `{ "userId": 42, "email": "…" }`,
either field may be `null`. Session **payload** remains on **`GET /sessions`** only.
### Paging and sorting
Paged list endpoints return **`{ items, page, pageSize, totalItems, totalPages }`**. Page size is
clamped to **`[1, 200]`**; query **`pageSize=0`** means default **20** (except where noted below).
| Endpoint | Search (`q`) | Sort (`sort` / `dir`) |
|----------|----------------|------------------------|
| `GET /users` | email, name, UID, role, status, id | `email`, `name`, `role`, `status`, `id` |
| `GET /audit/events` | — | fixed newest-first |
| `GET /audit/api-access` | — | fixed newest-first |
| `GET /sessions/admin` | id, user, app | session columns (see path) |
| `GET /sessions/my` | id, app, status | session columns (see path) |
| `GET /sessions/admin/analytics/concurrent-sessions` | — | fixed date ascending |
Admin session list page size is fixed by server config (`sessions.admin.page-size`, default **10**).
Export uses `sessions.export.page-size` (default **100**).
### Tokens
| Kind | Use |
|------|-----|
| **Firebase ID token** | `POST /workspaces` (create), `GET /users/memberships`, `POST /users/login`, `POST /users/from-invite`, `POST /users/anonymous`, `POST /sessions`, `POST /sessions/get-or-create`, `POST /sessions/renew/{sessionToken}` — header `Authorization: Bearer ` |
| **Internal USER JWT** | All other routes in this document — same header; issued by backend (`tokenType=USER`) |
### Related specs
- **Hosted login & application registration**: see **`/docs/openapi/integration-auth.yaml`**
- **AI session API only**: **`/docs/openapi/session/secure-flows-session-api.yaml`**
Tags marked **`human-only`** describe console-style usage (not the session-only AI surface).'
tags:
- name: Applications
description: Registered applications and redirect allowlists (ADMIN/OWNER)
paths:
/api/v1/applications:
post:
tags:
- Applications
summary: Register an application
description: Creates an application record under the workspace carried in the USER JWT (**ADMIN** or **OWNER**).
security:
- userBearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ClientAppRequest'
responses:
'200':
description: Application created
content:
application/json:
schema:
$ref: '#/components/schemas/ClientAppResponse'
'400':
description: Validation error
'403':
description: Forbidden
'409':
description: Duplicate appId
operationId: postApiV1Applications
x-operation-id-source: derived
get:
tags:
- Applications
summary: List applications for workspace (paged)
description: 'Paged list for the workspace admin console. Query params match `GET /users`:
`page`, `pageSize`, `q`, `sort`, `dir`. Sort keys: `displayName` (default), `appId`, `id`.'
security:
- userBearerAuth: []
parameters:
- name: page
in: query
schema:
type: integer
default: 0
description: Zero-based page index
- name: pageSize
in: query
schema:
type: integer
default: 0
description: Page size; `0` means server default (20), clamped to `[1, 200]`
- name: q
in: query
schema:
type: string
description: Search displayName, appId (clientId), or numeric id
- name: sort
in: query
schema:
type: string
default: displayName
enum:
- displayName
- appId
- id
- name: dir
in: query
schema:
type: string
default: asc
enum:
- asc
- desc
responses:
'200':
description: Paged applications
content:
application/json:
schema:
$ref: '#/components/schemas/ClientAppPageResponse'
'403':
description: Forbidden
operationId: getApiV1Applications
x-operation-id-source: derived
/api/v1/applications/{appId}:
get:
tags:
- Applications
summary: Get one application by id
security:
- userBearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
example: acme-web
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/ClientAppResponse'
'403':
description: Forbidden
'404':
description: Not found
operationId: getApiV1ApplicationsByAppId
x-operation-id-source: derived
patch:
tags:
- Applications
summary: Update display name and/or redirect URIs
security:
- userBearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
example: acme-web
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ClientAppPatchBody'
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/ClientAppResponse'
'403':
description: Forbidden
'404':
description: Not found
operationId: patchApiV1ApplicationsByAppId
x-operation-id-source: derived
delete:
tags:
- Applications
summary: Delete an application
security:
- userBearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
example: acme-web
responses:
'200':
description: Deleted
'403':
description: Forbidden
'404':
description: Not found
operationId: deleteApiV1ApplicationsByAppId
x-operation-id-source: derived
/api/v1/applications/{appId}/redirect-uris:
post:
tags:
- Applications
summary: Atomically append one redirect URI to the allowlist
description: 'Idempotent: no-op (no audit event) if the URI is already present. Unlike `PATCH
/applications/{appId}`, this never replaces the existing `redirectUris` set, so it is safe to
call concurrently without a read-modify-write race.'
security:
- userBearerAuth: []
parameters:
- name: appId
in: path
required: true
schema:
type: string
example: acme-web
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AppendRedirectUriRequest'
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/ClientAppResponse'
'400':
description: redirectUri is required
'403':
description: Forbidden
'404':
description: Not found
operationId: postApiV1ApplicationsByAppIdRedirectUris
x-operation-id-source: derived
/api/v1/applications/validate-redirect:
post:
tags:
- Applications
summary: Validate app id + redirect URI (public)
description: '**No authentication.** Used by hosted login before redirecting to the third-party app.'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RedirectValidationRequest'
responses:
'200':
description: Always 200; check `valid` and `reason`
content:
application/json:
schema:
$ref: '#/components/schemas/RedirectValidationResponse'
operationId: postApiV1ApplicationsValidateRedirect
x-operation-id-source: derived
components:
schemas:
AppendRedirectUriRequest:
type: object
required:
- redirectUri
properties:
redirectUri:
type: string
format: uri
example: https://acme.example/callback
ClientAppPatchBody:
type: object
description: Partial update; omit fields you do not change
properties:
displayName:
type: string
nullable: true
redirectUris:
type: array
nullable: true
items:
type: string
format: uri
sessionTokenTtlSeconds:
type: integer
format: int64
nullable: true
sessionPayloadTtlSeconds:
type: integer
format: int64
nullable: true
RedirectValidationRequest:
type: object
required:
- appId
- redirectUri
properties:
appId:
type: string
description: Same as `app_id` query parameter on hosted login
redirectUri:
type: string
format: uri
ClientAppRequest:
type: object
description: Create application (all fields required except TTL overrides)
required:
- appId
- displayName
- redirectUris
properties:
appId:
type: string
description: Stable id — use as `app_id` on hosted login
example: acme-web
displayName:
type: string
example: Acme Web App
redirectUris:
type: array
minItems: 1
items:
type: string
format: uri
sessionTokenTtlSeconds:
type: integer
format: int64
nullable: true
description: Optional per-app session JWT lifetime override (seconds)
sessionPayloadTtlSeconds:
type: integer
format: int64
nullable: true
description: Optional per-app payload TTL override (seconds; 0 = unlimited)
ClientAppResponse:
type: object
required:
- id
- workspaceId
- appId
- displayName
- redirectUris
properties:
id:
type: integer
format: int64
workspaceId:
type: integer
format: int64
appId:
type: string
displayName:
type: string
redirectUris:
type: array
items:
type: string
format: uri
sessionTokenTtlSeconds:
type: integer
format: int64
nullable: true
sessionPayloadTtlSeconds:
type: integer
format: int64
nullable: true
ClientAppPageResponse:
type: object
required:
- items
- page
- pageSize
- totalItems
- totalPages
properties:
items:
type: array
items:
$ref: '#/components/schemas/ClientAppResponse'
page:
type: integer
description: Zero-based page index
pageSize:
type: integer
totalItems:
type: integer
format: int64
totalPages:
type: integer
RedirectValidationResponse:
type: object
required:
- valid
properties:
valid:
type: boolean
appId:
type: string
nullable: true
redirectUri:
type: string
nullable: true
reason:
type: string
nullable: true
description: Human-readable; `"ok"` when valid
displayName:
type: string
nullable: true
description: Client application display name; only set when `valid` is `true`. Shown by hosted login on the account-confirmation prompt ("Continue as …?").
securitySchemes:
firebaseBearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: '**Firebase ID token** from the client SDK (`Authorization: Bearer <token>`).
When the token includes `email`, session endpoints best-effort persist it on the workspace end-user row
(audit display only; no extra request fields).
'
userBearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: '**Internal USER JWT** issued by this API (`tokenType=USER`). Contains workspace and role claims.
'
sessionBearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: 'Internal session JWT from `POST /api/v1/sessions` or `POST /api/v1/sessions/get-or-create`
(`tokenType=SESSION`; subject = session id).
'