Skip to content

API Reference

Floyi’s External API lets you access your data programmatically through a versioned REST API. Use it to connect AI agents, automate workflows with Zapier or Make, or build custom dashboards on top of your Floyi workspace.

  • How to create and manage API keys
  • How to authenticate API requests
  • All available V1 endpoints with examples
  • Permission scopes, rate limits, and error handling

Floyi uses a 4-level topical hierarchy. The API field names (used in JSON responses) differ from the display labels shown in the Floyi dashboard. Every API response includes a _meta object with the mapping, but here is the complete reference:

LevelAPI Field NameDisplay LabelDescription
0main_topicPillarTop-level topic category (e.g., “Email Marketing”)
1subtopic_2HubMajor subtopic grouping (e.g., “Email Automation”)
2subtopic_3BranchSpecific topic area (e.g., “Drip Campaigns”)
3subtopic_4ResourceIndividual content asset — can be an article, video, tool, calculator, or any content format (e.g., “Welcome Sequence Templates”)

Node types in the authority hierarchy also use internal labels that map to the same display names:

Internal TypeDisplay Label
PILLARPillar
HUBHub
BRANCHBranch
RESOURCEResource

[!IMPORTANT] Always use the display labels (Pillar, Hub, Branch, Resource) when presenting hierarchy data to users. The API field names (main_topic, subtopic_2, etc.) are internal identifiers that should not be shown in user-facing interfaces.

Every V1 API response includes a _meta object with:

  • description — What this endpoint returns and how to interpret the data
  • level_labels — Mapping from API field names to display labels (included on hierarchy endpoints)
  • node_type_labels — Mapping from internal node types to display labels (included on authority endpoints)

Example:

{
"_meta": {
"description": "Returns the full 4-level topical hierarchy...",
"level_labels": {
"main_topic": "Pillar",
"subtopic_2": "Hub",
"subtopic_3": "Branch",
"subtopic_4": "Resource"
}
},
"brand_id": "...",
"research_data": [...]
}

Topical Research vs. Topical Maps vs. Authority

Section titled “Topical Research vs. Topical Maps vs. Authority”
ModuleAPI EndpointContainsSearch Metrics?
Topical Research/api/v1/research/Topic hierarchy (taxonomy) with keyword annotationsNo — purely structural
Topical Maps/api/v1/maps/Raw keyword clusters with search volume, CPC, competition, SERP dataYes
Topical Authority/api/v1/authority/Enriched hierarchy with coverage, SERP rankings, AI search presenceYes

Standalone vs. Authority Content Workflows

Section titled “Standalone vs. Authority Content Workflows”

Floyi’s API supports two content generation workflows:

WorkflowBrief EndpointArticle EndpointUse Case
Standalone/api/v1/briefs//api/v1/content/articles/One-off briefs for any topic (query_text). Not linked to the authority hierarchy.
Authority/api/v1/authority/{brand_id}/briefs//api/v1/authority/{brand_id}/articles/Hierarchy-linked briefs by node_id. Tied to your topical map for the Planner tab.

[!TIP] Which should I use? If you have a topical map and want briefs/articles tracked in the Planner tab, use the Authority endpoints. If you want to generate a quick brief for any topic without hierarchy linkage, use the Standalone endpoints.


Floyi provides machine-readable API documentation for developer tools, AI coding assistants, and automation platforms.

ResourceURLDescription
Interactive Docs (Swagger UI)api.floyi.com/api/v1/docs/Browse and test endpoints in your browser
Alternative Viewer (ReDoc)api.floyi.com/api/v1/redoc/Clean, readable API reference
OpenAPI 3.0 Schema (YAML)api.floyi.com/api/v1/schema/Import into Postman, Insomnia, or any API client
LLM Referenceapi.floyi.com/llms-full.txtFull API reference optimized for AI coding assistants
LLM Summaryapi.floyi.com/llms.txtCompact endpoint listing for AI agents

The OpenAPI schema can be imported directly into tools like Postman or Insomnia to auto-generate request templates. AI coding assistants (Claude, ChatGPT, Cursor, etc.) can read the llms-full.txt file to understand the full API without needing authentication.


RequirementDetails
Floyi PlanAgency
API KeyCreated in Settings > API Keys
AuthenticationX-API-Key header on every request
WorkspaceX-Team-ID header (optional — omit for personal workspace)
Base URLhttps://api.floyi.com/api/v1/

[!NOTE] The External API is currently in beta. Access is limited to approved users. Contact support to request access.

API key creation requires an Agency plan. If you are on the Free, Creator, or Pro plan, the API Keys tab in Settings will prompt you to upgrade.

  1. Go to Settings > API Keys.
  2. Click Create API Key.
  3. Enter a name for the key (e.g., “My AI Agent” or “Zapier Integration”).
  4. Choose a key type (see Key Types below).
  5. Review and customize permissions if needed.
  6. Click Create.
  7. Copy the API key immediately. It is shown only once and cannot be retrieved later.

[!IMPORTANT] Store your API key securely. Treat it like a password. Never commit it to version control, share it in chat, or expose it in client-side code.

TypeDescriptionRate LimitDefault Permissions
IntegrationFor Zapier, Make, n8n, and workflow automation. Read and write access to core features.120 requests/minBrands, briefs, content, maps (read + write)
DeveloperFor custom apps, dashboards, and external tools. Read-only access to your own data.60 requests/minBrands, briefs, content, maps (read only)

All Floyi API keys follow the format:

fyi_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The fyi_live_ prefix identifies Floyi keys in logs and secret scanners. The full key is 44 characters.


Every API request must include your key in the X-API-Key header.

For POST, PUT, and PATCH requests, you must also set the Content-Type: application/json header and send a JSON request body.

Terminal window
# GET request (read)
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/brands/
# POST request (write)
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"brand_name": "My Brand"}' \
https://api.floyi.com/api/v1/brands/

[!TIP] Using a team workspace? API keys are account-level — they default to your personal workspace. To access a team’s data, add the X-Team-ID header with the team’s UUID (e.g., -H "X-Team-ID: a1b2c3d4-..." in curl). Without it, you’ll only see personal workspace data. See Workspace Selection below.

StatusMeaning
401 UnauthorizedMissing, invalid, expired, or revoked API key
403 ForbiddenValid key but missing the required permission scope
429 Too Many RequestsRate limit exceeded. Wait and retry.

A 401 response includes a description in the response body:

{
"detail": "Invalid API key."
}

Possible messages: "Invalid API key.", "API key has expired.", "API key has been revoked.", "User account is no longer active.", "Request from unauthorized IP address.", "The External API is currently in beta. Contact support to request access."

A 403 response means the key is valid but lacks the required scope:

{
"detail": "You do not have permission to perform this action."
}

Check your key’s assigned scopes in Settings > API Keys and ensure they include the scope listed for the endpoint you are calling (e.g., briefs:write for brief generation).

API keys are account-level — they are not tied to a specific workspace. To control which workspace your request operates on, use the optional X-Team-ID header.

X-Team-ID HeaderResult
OmittedPersonal workspace (your own brands, briefs, etc.)
Valid team UUIDTeam workspace (brands, briefs, etc. belonging to that team)
Invalid UUID403 Forbidden
UUID of a team you don’t belong to403 Forbidden

Discovering your team UUIDs:

Call the /api/v1/me/teams/ endpoint to list all teams you are an active member of. Each team object includes the id (UUID) you need for the X-Team-ID header.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/me/teams/
{
"_meta": { "description": "Lists all teams the authenticated user is an active member of..." },
"results": [
{
"team": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Acme Marketing",
"slug": "acme-marketing",
"plan_name": "Agency Plan",
"created_at": "2025-09-15T10:00:00Z"
},
"role": "owner",
"status": "active"
}
]
}

Using the team UUID in requests:

Terminal window
# Personal workspace (no header)
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/brands/
# Team workspace
curl -H "X-API-Key: fyi_live_your_key_here" \
-H "X-Team-ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
https://api.floyi.com/api/v1/brands/

[!TIP] You can use the same API key for both personal and team workspaces. The X-Team-ID header is the only thing that determines which workspace a request operates on. You can access any team where you are an active member.


Each API key has a set of permission scopes that control which endpoints it can access. You can customize scopes when creating a key.

ScopeDescription
authority:readRead topical authority hierarchy, SERP data, and AI search presence
authority:writeToggle published status on authority map nodes
brands:readList and read brand details
brands:writeCreate and update brands
briefs:readList and read content briefs
briefs:writeCreate and trigger brief generation
clustering:readList and read clustering reports and SERP data
clustering:writeStart clustering, recluster, and delete reports
content:readList and read articles and content
content:writeCreate articles, trigger draft generation
maps:readList and read raw topical map data
research:readRead topical research data, stats, task status, diff comparison
research:writeAdd, rename, delete, move, merge nodes, update keywords
user:readRead your own profile, credit balance, teams, and audit logs

Rate limits are applied per key based on the key type.

Key TypeLimit
Developer60 requests per minute
Integration120 requests per minute

When you exceed the rate limit, the API returns a 429 Too Many Requests response with a Retry-After header indicating how many seconds to wait.

{
"detail": "Request was throttled. Expected available in 12 seconds."
}

All endpoints are under /api/v1/. Responses are JSON. List endpoints return arrays of objects. Detail endpoints return a single object.

Scope required: brands:read (GET), brands:write (POST)

GET /api/v1/brands/

Returns all brands in your workspace, ordered by most recently created.

Query parameters:

ParameterTypeDescription
searchstringSearch brands by name (case-insensitive)
Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/brands/
# Search by name
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/brands/?search=floyi"

Response:

[
{
"id": "a1b2c3d4-...",
"brand_name": "Floyi",
"website_url": "https://floyi.com",
"mission": "...",
"vision": "...",
"tagline": "...",
"target_audience": "...",
"brand_voice": "...",
"values": "...",
"marketplace": "...",
"market_position": "...",
"key_competitors": "...",
"unique_selling_proposition": "...",
"brand_personality": "...",
"brand_story": "...",
"language": "en",
"country_code": "US",
"country_name": "United States",
"stage": "completed",
"content_scope": "...",
"created_at": "2026-02-01T10:00:00Z",
"updated_at": "2026-02-15T14:30:00Z"
}
]
GET /api/v1/brands/{id}/

Returns full details for a single brand. The response shape is the same as each object in the list endpoint. Returns 404 if the brand is not found or you do not have access.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/brands/a1b2c3d4-.../

Response:

{
"id": "a1b2c3d4-...",
"brand_name": "Floyi",
"website_url": "https://floyi.com",
"mission": "...",
"vision": "...",
"tagline": "...",
"target_audience": "...",
"brand_voice": "...",
"values": "...",
"marketplace": "...",
"market_position": "...",
"key_competitors": "...",
"unique_selling_proposition": "...",
"brand_personality": "...",
"brand_story": "...",
"language": "en",
"country_code": "US",
"country_name": "United States",
"stage": "completed",
"content_scope": "...",
"created_at": "2026-02-01T10:00:00Z",
"updated_at": "2026-02-15T14:30:00Z"
}
POST /api/v1/brands/

Request body:

{
"brand_name": "My New Brand",
"website_url": "https://example.com",
"mission": "Help teams create better content",
"target_audience": "Content marketers and SEO professionals",
"language": "en"
}

Required fields: brand_name

Optional fields: website_url, mission, vision, tagline, target_audience, brand_voice, values, marketplace, key_competitors, unique_selling_proposition, description, language

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{
"brand_name": "My New Brand",
"website_url": "https://example.com",
"mission": "Help teams create better content",
"target_audience": "Content marketers and SEO professionals",
"language": "en"
}' \
https://api.floyi.com/api/v1/brands/

Response (201 Created):

{
"id": "a1b2c3d4-...",
"brand_name": "My New Brand",
"website_url": "https://example.com",
"mission": "Help teams create better content",
"vision": null,
"tagline": null,
"target_audience": "Content marketers and SEO professionals",
"brand_voice": null,
"values": null,
"marketplace": null,
"market_position": null,
"key_competitors": null,
"unique_selling_proposition": null,
"brand_personality": null,
"brand_story": null,
"language": "en",
"country_code": null,
"country_name": null,
"stage": "new",
"content_scope": null,
"created_at": "2026-02-22T10:00:00Z",
"updated_at": "2026-02-22T10:00:00Z"
}

The response returns the full brand object, including the id you need for subsequent API calls (briefs, maps, articles).

Error responses:

StatusCause
400 Bad RequestMissing brand_name or validation error. Response body contains field-level errors.
{
"brand_name": ["This field is required."]
}

Scope required: briefs:read (GET), briefs:write (POST)

GET /api/v1/briefs/

Returns all content briefs in your workspace.

Query parameters:

ParameterTypeDescription
brand_idUUIDFilter briefs by brand
statusstringFilter by brief status (e.g., COMPLETE, PENDING, PROCESSING)
searchstringSearch by topic/query text or generated title (case-insensitive)
Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/briefs/?brand_id=a1b2c3d4-..."
# Search by topic name
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/briefs/?search=what+is+topical+authority"

Response:

[
{
"id": "b5c6d7e8-...",
"query_text": "best seo tools for agencies",
"brand_name": "Floyi",
"status": "COMPLETE",
"generated_title": "Best SEO Tools for Agencies in 2026",
"generated_meta_description": "Discover the top SEO tools...",
"created_at": "2026-02-10T08:00:00Z",
"updated_at": "2026-02-10T08:15:00Z"
}
]
GET /api/v1/briefs/{id}/

Returns the full brief including the complete result_json and curated_brief_json with all SERP analysis, competitor data, headings, and recommendations. Returns 404 if the brief is not found or you do not have access.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/briefs/b5c6d7e8-.../

Response:

{
"id": "b5c6d7e8-...",
"query_text": "best seo tools for agencies",
"brand_name": "Floyi",
"status": "COMPLETE",
"generated_title": "Best SEO Tools for Agencies in 2026",
"generated_meta_description": "Discover the top SEO tools...",
"result_json": {
"header_sections": [ ... ],
"serp_analysis": { ... },
"competitor_data": [ ... ],
"keyword_recommendations": [ ... ]
},
"curated_brief_json": {
"header_sections": [ ... ],
"meta_title": "...",
"meta_description": "..."
},
"input_params": {
"query_text": "best seo tools for agencies",
"brand_id": "a1b2c3d4-...",
"selected_serp_data": [ ... ]
},
"created_at": "2026-02-10T08:00:00Z",
"updated_at": "2026-02-10T08:15:00Z"
}

Detail-only fields (not included in the list endpoint):

FieldTypeDescription
result_jsonobjectThe raw brief output from the AI agent. Contains header_sections (outline with headings, subheadings, and talking points), serp_analysis, competitor_data, and keyword_recommendations. Structure varies based on the brief agent version.
curated_brief_jsonobjectThe user-edited version of the brief (if the user customized it in the Floyi editor). Same structure as result_json. null if no edits have been made.
input_paramsobjectThe original request parameters used to generate this brief, including query_text, brand_id, selected_serp_data, and any optional fields.

[!NOTE] The result_json and curated_brief_json fields contain complex nested structures produced by the brief generation agent. The exact shape may vary, but both always include a header_sections array representing the content outline.

GET /api/v1/briefs/{id}/status/

Returns just the status of a brief. Useful for polling during brief generation.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/briefs/b5c6d7e8-.../status/

Response:

{
"id": "b5c6d7e8-...",
"status": "COMPLETE",
"query_text": "best seo tools for agencies",
"generated_title": "Best SEO Tools for Agencies in 2026"
}

Status values:

StatusDescription
DRAFTBrief created but generation has not started
PENDINGBrief is queued for generation
PROCESSINGBrief generation is actively running
AWAITING_OUTLINE_REVIEWGeneration paused for user outline review (interactive mode)
RESUMING_PROCESSINGGeneration resuming after outline review
RETRY_PAUSEDGeneration paused due to a transient error; will retry automatically
COMPLETEBrief generation finished successfully
PARTIAL_COMPLETEBrief generated but some sections may be incomplete
FAILEDBrief generation failed

[!TIP] When polling, treat COMPLETE and PARTIAL_COMPLETE as terminal success states, and FAILED as a terminal error state. All other statuses indicate the brief is still in progress.

POST /api/v1/briefs/generate/

Triggers standalone content brief generation for any topic. This is a freeform endpoint — you provide the topic text directly. For hierarchy-linked briefs (tied to your topical authority map), use the Authority Briefs endpoints instead.

Returns immediately with a 202 Accepted response. Poll the status endpoint for progress.

Request body:

{
"query_text": "best seo tools for agencies",
"brand_id": "a1b2c3d4-...",
"ai_model_id": "gpt-5-mini"
}

Required fields: query_text, brand_id

Optional fields:

FieldTypeDescription
selected_serp_dataobject[]SERP competitor pages to analyze (max 15, each must include url). If omitted, auto-fetched from cached SERP data for this keyword in the topical map. Returns 400 if no cached data exists.
user_provided_keywordsstring[]Additional keywords to include in the brief
internal_link_suggestionsobject[]Internal links to suggest (each: url, anchor_text)
content_info_contextobjectAdditional context (SERP features, AI overview data, etc.)
ai_model_idstringAI model to use (e.g. "gpt-5-mini"). Uses default if not specified.
Terminal window
# Minimal
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{
"query_text": "best seo tools for agencies",
"brand_id": "a1b2c3d4-..."
}' \
https://api.floyi.com/api/v1/briefs/generate/
# With SERP data and keywords
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{
"query_text": "best seo tools for agencies",
"brand_id": "a1b2c3d4-...",
"selected_serp_data": [
{"url": "https://example.com", "title": "Example", "snippet": "..."}
],
"user_provided_keywords": ["seo software", "agency tools"]
}' \
https://api.floyi.com/api/v1/briefs/generate/

Response (202 Accepted):

{
"id": "b5c6d7e8-...",
"status": "PENDING",
"query_text": "best seo tools for agencies",
"brand_name": "Floyi",
"message": "Brief generation started. Poll /api/v1/briefs/{id}/status/ for progress."
}

[!TIP] After generating a brief, poll GET /api/v1/briefs/{id}/status/ every 10-15 seconds until the status changes to COMPLETE. Brief generation typically takes 1-3 minutes depending on the number of SERP pages to analyze.

Error responses:

StatusCause
400 Bad RequestValidation error (missing required fields, SERP entry missing url, or no SERP data available)
402 Payment RequiredInsufficient credits to generate a brief
404 Not FoundBrand not found or you do not have access

400 — No SERP data available (auto-fetch):

When selected_serp_data is omitted, the API attempts to auto-fetch cached SERP data for the topic from the brand’s topical map. If no cached SERP data exists for that keyword, the request fails with a 400:

{
"detail": "No SERP data available for this topic. Please provide selected_serp_data or ensure SERP data has been collected for this topic in the topical map."
}

To resolve this, either:

  1. Provide selected_serp_data manually with competitor pages you want analyzed, or
  2. Ensure SERP data has been collected for this topic in the topical map first (via the Floyi dashboard)

400 — SERP entry missing url:

{
"detail": "selected_serp_data[0] must include a 'url' field."
}

402 — Insufficient credits:

{
"detail": "Insufficient credits."
}

404 — Brand not found:

{
"detail": "Brand not found or you do not have access."
}

[!NOTE] Standalone briefs are not linked to the authority hierarchy. If you need briefs tied to specific topics in your topical map (for the Planner tab), use POST /api/v1/authority/{brand_id}/briefs/generate/ instead.


Scope required: content:read (GET), content:write (POST)

GET /api/v1/content/articles/

Returns all content articles in your workspace.

Query parameters:

ParameterTypeDescription
brand_idUUIDFilter articles by brand
searchstringSearch by article title (case-insensitive)
Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/content/articles/?brand_id=a1b2c3d4-..."
# Search by title
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/content/articles/?search=seo+tools"

Response:

[
{
"id": "c7d8e9f0-...",
"title": "Best SEO Tools for Agencies in 2026",
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"machine_state": "completed",
"editorial_state": "draft",
"created_at": "2026-02-12T09:00:00Z",
"updated_at": "2026-02-14T11:00:00Z"
}
]
GET /api/v1/content/articles/{id}/

Returns the full article including brief_id, additional_directions, and all metadata. Returns 404 if the article is not found or you do not have access.

Response:

{
"id": "c7d8e9f0-...",
"title": "Best SEO Tools for Agencies in 2026",
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"brief_id": "b5c6d7e8-...",
"machine_state": "completed",
"editorial_state": "draft",
"additional_directions": "Focus on enterprise pricing tiers and team collaboration features.",
"created_at": "2026-02-12T09:00:00Z",
"updated_at": "2026-02-14T11:00:00Z"
}

Detail-only fields (not included in the list endpoint):

FieldTypeDescription
brief_idUUID or nullThe content brief this article was created from. null if the article was created without a brief.
additional_directionsstring or nullCustom instructions provided for draft generation. null if none were set.
POST /api/v1/content/articles/generate/

Creates a new article from a completed content brief and immediately starts AI draft generation — one step instead of two. The brief must be in COMPLETE or PARTIAL_COMPLETE status and have generated sections.

Request body:

{
"brief_id": "b5c6d7e8-...",
"ai_model_id": "claude-sonnet-4",
"intent": "human",
"specialists": {
"web_research": true,
"fact_check": true,
"intro_key_takeaways": true,
"web_research_mode": "basic"
}
}

Required fields: brief_id, ai_model_id

Optional fields:

FieldTypeDefaultDescription
intentstring"human"Writing style — "human" for natural tone
specialistsobjectall falseSpecialist agents to enable during generation (see below)

Specialist agents:

SpecialistDescriptionAvailability
web_researchResearches the web for up-to-date informationResource pages only
fact_checkVerifies claims and data accuracyResource pages only
intro_key_takeawaysGenerates a polished intro and key takeaways sectionResource pages only
conversion_coachAdds conversion-optimized CTAs and messagingLocal/landing pages only
web_research_mode"basic" or "advanced" depth for web researchWhen web_research is true

[!NOTE] Specialist availability depends on the article type. Resource pages (blog posts, guides) can use web_research, fact_check, and intro_key_takeaways. Local/landing pages automatically get conversion_coach enabled. The API filters specialists to match the article type.

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"brief_id": "b5c6d7e8-...", "ai_model_id": "claude-sonnet-4"}' \
https://api.floyi.com/api/v1/content/articles/generate/

Response (202 Accepted):

{
"id": "c7d8e9f0-...",
"brief_id": "b5c6d7e8-...",
"title": "Best SEO Tools for Agencies in 2026",
"task_id": "e1f2a3b4-...",
"status": "generating",
"message": "Article created and draft generation started. Poll /api/v1/content/articles/{id}/status/ for progress."
}

[!TIP] After triggering generation, poll GET /api/v1/content/articles/{id}/status/ every 15-30 seconds. Draft generation typically takes 3-10 minutes depending on the number of sections and specialists enabled.

Error responses:

StatusCause
400 Bad Requestbrief_id or ai_model_id missing, brief not in COMPLETE/PARTIAL_COMPLETE status, brief has no associated brand, or brief has no content sections
402 Payment RequiredInsufficient credits for draft or specialist agents
404 Not FoundBrief or brand not found, or you do not have access
POST /api/v1/content/articles/{id}/generate/

Regenerates draft for an existing article. Creates a new version, re-syncs sections from the brief, resets all sections, and generates fresh content. Optionally accepts a different brief_id to switch briefs.

Request body:

{
"ai_model_id": "claude-sonnet-4",
"brief_id": "b5c6d7e8-...",
"intent": "human",
"specialists": {
"web_research": true,
"fact_check": true,
"intro_key_takeaways": true,
"web_research_mode": "basic"
}
}

Required fields: ai_model_id

Optional fields: brief_id (switch to a different brief), intent, specialists

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"ai_model_id": "claude-sonnet-4"}' \
https://api.floyi.com/api/v1/content/articles/c7d8e9f0-.../generate/

Response (202 Accepted):

{
"id": "c7d8e9f0-...",
"brief_id": "b5c6d7e8-...",
"title": "Best SEO Tools for Agencies in 2026",
"task_id": "e1f2a3b4-...",
"status": "regenerating",
"message": "Draft regeneration started. Poll /api/v1/content/articles/{id}/status/ for progress."
}

Error responses:

StatusCause
400 Bad RequestMissing ai_model_id
402 Payment RequiredInsufficient credits for draft or specialist agents
409 ConflictArticle generation already in progress

409 — Already in progress:

{
"detail": "Article generation already in progress."
}

402 — Insufficient credits:

{
"detail": "Insufficient credits."
}
GET /api/v1/content/articles/{id}/status/

Returns the current generation progress of an article. Useful for polling during draft generation.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/content/articles/c7d8e9f0-.../status/

Response:

{
"id": "c7d8e9f0-...",
"machine_state": "in_progress",
"sections_total": 8,
"sections_approved": 3,
"sections_drafting": 2,
"sections_not_started": 3,
"sections_needs_attention": 0,
"completion_percentage": 37.5,
"specialists_running": true,
"specialists_complete": false
}

Machine state values:

StateDescription
readyArticle created, waiting for draft generation
in_progressDraft generation is actively running
draft_doneAll sections drafted successfully
incompleteGeneration finished but some sections may need attention

[!TIP] When polling, treat draft_done as the terminal success state. Once complete, fetch the full article with GET /api/v1/content/articles/{id}/ to see the final content.


Scope required: maps:read

Returns the raw topical map data as created during keyword research and clustering, before any Topical Authority overrides are applied. For the enriched authority view (with organizer edits, SERP rankings, importance scores, and AI search presence), use the Topical Authority endpoints instead.

GET /api/v1/maps/

Returns all topical maps in your workspace.

Query parameters:

ParameterTypeDescription
brand_idUUIDFilter maps by brand
Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/maps/
# Filter by brand
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/maps/?brand_id=a1b2c3d4-..."

Response:

[
{
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"is_uploaded": false,
"created_at": "2026-01-20T12:00:00Z",
"updated_at": "2026-02-18T16:00:00Z"
}
]
GET /api/v1/maps/{brand_id}/

Returns the full raw keyword clusters from the topical map, including all search metrics, SERP analysis, and content metadata. Each cluster contains its centroid keyword and all associated keywords with their complete data. Returns 404 if no map exists for this brand or you do not have access.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/maps/a1b2c3d4-.../

Response:

{
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"is_uploaded": false,
"cluster_count": 85,
"clusters": [
{
"id": "c1d2e3f4-...",
"centroid": "best keyword research tools",
"keyword_count": 3,
"keywords": [
{
"keyword": "best keyword research tools",
"main_topic": "SEO Strategy",
"subtopic_2": "Keyword Research",
"subtopic_3": "Keyword Tools",
"subtopic_4": "best keyword research tools",
"sort_order": 0,
"search_volume": 2400,
"cpc": 3.50,
"competition": 0.72,
"url_slug": "best-keyword-research-tools",
"has_serp_data": true,
"serp_analysis": "Informational listicle format dominates...",
"serp_competitors": "ahrefs.com, semrush.com, moz.com",
"serp_freshness": "2025-12",
"content_title": "Best Keyword Research Tools",
"search_intent": "informational",
"buyers_journey": "consideration",
"content_type": "listicle",
"snippet": "Discover the top keyword research tools...",
"similarity": 0.95
}
]
}
],
"created_at": "2026-01-20T12:00:00Z",
"updated_at": "2026-02-18T16:00:00Z"
}

Cluster fields:

FieldTypeDescription
idstringCluster identifier
centroidstringThe primary keyword representing this cluster
keyword_countintegerNumber of keywords in this cluster
keywordsobject[]All keywords in this cluster

Keyword fields — Hierarchy:

FieldTypeDescription
keywordstringThe keyword text
main_topicstringMain Topic (level 1 of the hierarchy)
subtopic_2stringSubtopic 2 (level 2)
subtopic_3stringSubtopic 3 (level 3)
subtopic_4stringSubtopic 4 (level 4)
sort_orderintegerSort position within the cluster

Keyword fields — Search Metrics:

FieldTypeDescription
search_volumenumberMonthly search volume
cpcnumberCost per click (USD)
competitionnumberCompetition score (0–1)

Keyword fields — SERP Data:

FieldTypeDescription
has_serp_databooleanWhether SERP analysis data is available
serp_analysisstringSERP analysis summary
serp_competitorsstringTop competing domains in SERP
serp_freshnessstringSERP freshness / recency indicator

Keyword fields — Content & URL:

FieldTypeDescription
url_slugstringSuggested URL slug
content_titlestringSuggested content title
search_intentstringSearch intent classification
buyers_journeystringBuyer’s journey stage
content_typestringRecommended content format
snippetstringContent snippet / description
similaritynumber/stringSimilarity score to cluster centroid

[!TIP] This returns the original keyword research data. If the user has made edits in Floyi’s Organizer (renames, moves, combines), those changes are not reflected here. Use the Topical Authority endpoints to see the current effective hierarchy with all edits applied.


Scope required: research:read (GET), research:write (PATCH/POST)

Access the pre-clustering topical research tree — the 4-level topic hierarchy (Main Topics > Subtopic 2 > Subtopic 3 > Subtopic 4 > Keywords) that users build during the research phase before clustering into a topical map. These endpoints support both reading the tree and making atomic modifications (rename, add, delete, move, merge, keyword updates).

GET /api/v1/research/

Returns all topical research records in your workspace.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/research/

Response:

[
{
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"core_topic": "content strategy",
"created_at": "2026-02-01T10:00:00Z",
"updated_at": "2026-02-20T14:30:00Z"
}
]
GET /api/v1/research/{brand_id}/

Returns the full 4-level topic hierarchy with computed stats and generation status. Returns 404 if no research data exists for this brand.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/research/{BRAND_ID}/

Response:

{
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"core_topic": "content strategy",
"research_data": [
{
"main_topic": "email marketing",
"subtopic_2": [
{
"name": "email automation",
"subtopic_3": [...],
"subtopic_4": [],
"keywords": []
}
],
"subtopic_3": [],
"subtopic_4": [],
"keywords": []
}
],
"stats": {
"main_topic_count": 5,
"st2_count": 23,
"st3_count": 67,
"st4_count": 142,
"keyword_count": 890,
"leaf_nodes_without_keywords": 12,
"total_nodes": 237
},
"generation_status": {
"has_running_task": false
},
"created_at": "2026-02-01T10:00:00Z",
"updated_at": "2026-02-20T14:30:00Z"
}
GET /api/v1/research/{brand_id}/stats/

Returns only the stats without the full tree. Includes per-main-topic breakdown.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/research/{BRAND_ID}/stats/

Response:

{
"brand_id": "a1b2c3d4-...",
"main_topic_count": 5,
"st2_count": 23,
"st3_count": 67,
"st4_count": 142,
"keyword_count": 890,
"leaf_nodes_without_keywords": 12,
"total_nodes": 237,
"main_topics": [
{"name": "email marketing", "st2_count": 6, "st3_count": 18, "st4_count": 42, "keyword_count": 234}
],
"generation_status": {"has_running_task": false}
}
GET /api/v1/research/{brand_id}/task-status/

Poll the status of any running AI generation task. Performs Celery reconciliation — if the model says a task is running but Celery reports it as finished, the status is synced.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/research/{BRAND_ID}/task-status/

Response (task running):

{
"has_running_task": true,
"task_id": "3a8c1d2e-...",
"task_type": "generate_st2_st3_v2",
"task_status": "running",
"progress": {"current": 3, "total": 5, "message": "Generating ST2+ST3 for main topic 3 of 5..."},
"started_at": "2026-02-23T14:10:00+00:00",
"error": null
}

Response (no task):

{
"has_running_task": false
}

[!IMPORTANT] All write operations below reject with 409 Conflict if a generation task is currently running. Wait for the task to complete or cancel it from the Floyi dashboard before making changes.

PATCH /api/v1/research/{brand_id}/nodes/rename/

Scope required: research:write

Request body:

FieldTypeRequiredDescription
pathstring[]YesPath to the node (e.g., ["email marketing", "email automation"])
new_namestringYesNew name for the node (lowercased automatically)
Terminal window
curl -X PATCH \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"path": ["email marketing", "email automation"], "new_name": "marketing automation"}' \
https://api.floyi.com/api/v1/research/{BRAND_ID}/nodes/rename/

Response:

{
"success": true,
"operation": "rename",
"path": ["email marketing", "email automation"],
"old_name": "email automation",
"new_name": "marketing automation",
"updated_path": ["email marketing", "marketing automation"]
}
POST /api/v1/research/{brand_id}/nodes/add/

Scope required: research:write

Adds one node per request. To add multiple nodes at once, use Bulk Operations below instead.

Request body:

FieldTypeRequiredDescription
parent_pathstring[]YesPath to parent node. The depth determines the level of the new node (see examples below).
namestringYesName of the new topic (lowercased automatically)
positioninteger or nullNoInsertion index. null appends to end.

parent_path determines the node level:

parent_pathNew node level
[] (empty array)Pillar (root level)
["email marketing"]Hub under that Pillar
["email marketing", "automation"]Branch
["email marketing", "automation", "drip campaigns"]Resource (leaf level)
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"parent_path": ["email marketing"], "name": "email deliverability"}' \
https://api.floyi.com/api/v1/research/{BRAND_ID}/nodes/add/

Response:

{
"success": true,
"operation": "add",
"parent_path": ["email marketing"],
"name": "email deliverability",
"level": "ST2",
"path": ["email marketing", "email deliverability"]
}
POST /api/v1/research/{brand_id}/nodes/delete/

Scope required: research:write

Deletes a node and all its descendants (subtopics and keywords).

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"path": ["email marketing", "email automation", "trigger-based emails"]}' \
https://api.floyi.com/api/v1/research/{BRAND_ID}/nodes/delete/

Response:

{
"success": true,
"operation": "delete",
"path": ["email marketing", "email automation", "trigger-based emails"],
"deleted_node": "trigger-based emails",
"deleted_descendants": 4,
"deleted_keywords": 12
}
PATCH /api/v1/research/{brand_id}/nodes/keywords/

Scope required: research:write

Updates keywords on one node per request (but you can add/remove multiple keywords in that call). To update keywords on many nodes at once, use Bulk Operations below with the update_keywords action.

Keywords can be added to any level of the tree — Pillars, Hubs, Branches, and Resources all hold keywords.

Request body:

FieldTypeRequiredDescription
pathstring[]YesPath to the target node. Works at any level (Pillar, Hub, Branch, or Resource).
addstring[]NoKeywords to add (lowercased, duplicates skipped). Max 200 per request.
removestring[]NoKeywords to remove (missing ones skipped). Max 200 per request.

At least one of add or remove must be a non-empty array. Each array accepts up to 200 keywords per request — if you need more, split across multiple calls.

Which nodes can have keywords?

All levels. The path depth determines which node receives the keywords:

pathTarget node
["email marketing"]Pillar node
["email marketing", "email automation"]Hub node
["email marketing", "email automation", "drip campaigns"]Branch node
["email marketing", "email automation", "drip campaigns", "welcome sequences"]Resource node
Terminal window
curl -X PATCH \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"path": ["email marketing", "email automation"], "add": ["drip campaign"], "remove": ["old keyword"]}' \
https://api.floyi.com/api/v1/research/{BRAND_ID}/nodes/keywords/

Response:

{
"success": true,
"operation": "update_keywords",
"path": ["email marketing", "email automation"],
"added": ["drip campaign"],
"removed": ["old keyword"],
"current_keywords": ["email tools", "drip campaign"]
}
POST /api/v1/research/{brand_id}/nodes/move/

Scope required: research:write

Move a node (and its entire subtree) to a different parent. Use an empty target_parent_path ([]) to promote a node to a Main Topic.

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"source_path": ["content marketing", "outreach"], "target_parent_path": ["seo", "link building"]}' \
https://api.floyi.com/api/v1/research/{BRAND_ID}/nodes/move/

Response:

{
"success": true,
"operation": "move",
"source_path": ["content marketing", "outreach"],
"target_parent_path": ["seo", "link building"],
"new_path": ["seo", "link building", "outreach"]
}
POST /api/v1/research/{brand_id}/nodes/merge/

Scope required: research:write

Merge two same-level nodes under the same parent. Children and keywords from merge_path are moved to keep_path, then merge_path is deleted.

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"keep_path": ["email marketing", "email automation"], "merge_path": ["email marketing", "marketing automation"]}' \
https://api.floyi.com/api/v1/research/{BRAND_ID}/nodes/merge/

Response:

{
"success": true,
"operation": "merge",
"keep_path": ["email marketing", "email automation"],
"merged_from": "marketing automation",
"children_moved": 3,
"keywords_merged": 8
}
Section titled “Bulk Operations (Recommended for Multiple Changes)”
POST /api/v1/research/{brand_id}/nodes/bulk/

Scope required: research:write

This is the recommended endpoint for building or modifying hierarchies. Execute up to 200 operations in a single atomic request (all-or-nothing). Operations are applied sequentially — later operations see changes from earlier ones, so you can create a parent node and immediately add children to it in the same request.

Supported actions: add, rename, delete, move, merge, update_keywords

Each action uses the same parameters as its individual endpoint (see above).

Individual vs Bulk — when to use which:

EndpointUse case
nodes/addAdd a single node
nodes/keywordsUpdate keywords on a single node
nodes/bulkBuild hierarchies, batch edits, or any multi-step change (up to 200 ops, atomic)

Example: Build a full Pillar → Hub → Branch → Resource hierarchy with keywords in one request:

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{"action": "add", "parent_path": [], "name": "email marketing"},
{"action": "add", "parent_path": ["email marketing"], "name": "email automation"},
{"action": "add", "parent_path": ["email marketing"], "name": "email deliverability"},
{"action": "add", "parent_path": ["email marketing", "email automation"], "name": "drip campaigns"},
{"action": "add", "parent_path": ["email marketing", "email automation"], "name": "triggered emails"},
{"action": "add", "parent_path": ["email marketing", "email automation", "drip campaigns"], "name": "welcome sequences"},
{"action": "add", "parent_path": ["email marketing", "email automation", "drip campaigns"], "name": "onboarding flows"},
{"action": "update_keywords", "path": ["email marketing"], "add": ["email marketing strategy", "email campaigns"]},
{"action": "update_keywords", "path": ["email marketing", "email automation"], "add": ["marketing automation tools", "email workflow"]},
{"action": "update_keywords", "path": ["email marketing", "email automation", "drip campaigns", "welcome sequences"], "add": ["welcome email series", "new subscriber emails", "welcome email template"]}
]
}' \
https://api.floyi.com/api/v1/research/{BRAND_ID}/nodes/bulk/

This creates the following structure in a single atomic request:

email marketing (Pillar) ← keywords: email marketing strategy, email campaigns
├── email automation (Hub) ← keywords: marketing automation tools, email workflow
│ ├── drip campaigns (Branch)
│ │ ├── welcome sequences (Resource) ← keywords: welcome email series, new subscriber emails, welcome email template
│ │ └── onboarding flows (Resource)
│ └── triggered emails (Branch)
└── email deliverability (Hub)

Simple batch example:

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{"action": "rename", "path": ["seo tools", "keyword research"], "new_name": "keyword research tools"},
{"action": "add", "parent_path": ["seo tools"], "name": "link building tools"},
{"action": "delete", "path": ["seo tools", "deprecated category"]}
]
}' \
https://api.floyi.com/api/v1/research/{BRAND_ID}/nodes/bulk/

Atomicity: If any operation fails, all previous operations in the batch are rolled back. No partial changes are applied.

Response (success):

{
"success": true,
"operations_applied": 3,
"results": [
{"operation": "rename", "success": true, "old_name": "keyword research", "new_name": "keyword research tools"},
{"operation": "add", "success": true, "name": "link building tools", "level": "ST2"},
{"operation": "delete", "success": true, "deleted_node": "deprecated category", "deleted_descendants": 2, "deleted_keywords": 5}
]
}

Response (failure — all rolled back):

{
"success": false,
"error": "Operation 2 (add) failed: Name already exists at this level.",
"failed_at_index": 1,
"operations_rolled_back": 1,
"message": "All operations rolled back. No changes were applied."
}
POST /api/v1/research/{brand_id}/diff/

Scope required: research:read

Compare two tree states and return a structured diff. Useful for agents to summarize changes before confirming with the user.

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"before": [...], "after": [...]}' \
https://api.floyi.com/api/v1/research/{BRAND_ID}/diff/

Response:

{
"changes": [
{"type": "added", "level": "ST2", "path": ["seo", "link building tools"], "name": "link building tools"},
{"type": "deleted", "level": "ST3", "path": ["seo", "old category"], "name": "old category", "descendants_deleted": 3}
],
"summary": {
"nodes_added": 1,
"nodes_deleted": 1,
"nodes_renamed": 0,
"nodes_moved": 0,
"keywords_added": 0,
"keywords_removed": 0
}
}

Limits: Combined before + after payload must not exceed 2MB. Combined node count must not exceed 5,000.

Error responses for all write endpoints:

StatusWhen
400 Bad RequestInvalid request body, missing required fields, validation failure
404 Not FoundBrand or research record not found
409 ConflictName already exists, or generation task is running
413 Payload Too LargeDiff payload exceeds 2MB

Scope required: authority:read (GET), authority:write (PATCH)

Returns the authority-enriched hierarchy with all organizer overrides applied, plus coverage data (importance scores, published status), SERP rankings, and AI search presence. This is the same view shown in the Floyi dashboard’s Topical Authority section.

GET /api/v1/authority/

Returns all authority maps in your workspace.

Query parameters:

ParameterTypeDescription
brand_idUUIDFilter by brand
Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/authority/
# Filter by brand
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/authority/?brand_id=a1b2c3d4-..."

Response:

[
{
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"is_uploaded": false,
"created_at": "2026-01-20T12:00:00Z",
"updated_at": "2026-02-18T16:00:00Z"
}
]
GET /api/v1/authority/{brand_id}/

Returns the current effective hierarchy for an authority map. This includes all user edits from the Organizer (renames, moves, combines, new topics) applied on top of the base map data. It returns the same view of the map that the Floyi dashboard shows. Returns 404 if no map exists for this brand or you do not have access.

Each node in the hierarchy array represents a topic cluster with its position in the 4-level hierarchy (Main Topic > Subtopic 2 > Subtopic 3 > Subtopic 4), keywords, published status, importance score, SERP ranking, and AI search presence.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../

Response:

{
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"is_uploaded": false,
"node_count": 142,
"hierarchy": [
{
"node_id": "f1a2b3c4-...",
"name": "best keyword research tools",
"type": "RESOURCE",
"source": "resources",
"parent_id": "d4e5f6a7-...",
"mt": "SEO Strategy",
"st2": "Keyword Research",
"st3": "Keyword Tools",
"st4": "best keyword research tools",
"keywords": ["best keyword research tools", "keyword research software", "top keyword tools"],
"keyword_count": 3,
"url_slug": "best-keyword-research-tools",
"published": true,
"importance": 82.3,
"priority_category": "Medium",
"serp_position": 4,
"serp_all_positions": [4, 12],
"aio_status": "cited",
"aimode_status": "mentioned",
"chatgpt_status": "N/A"
},
{
"node_id": "a5b6c7d8-...",
"name": "SEO Strategy",
"type": "PILLAR",
"mt": "SEO Strategy",
"st2": "SEO Strategy",
"st3": "SEO Strategy",
"st4": "SEO Strategy",
"keywords": ["seo strategy", "seo planning", "search engine optimization strategy"],
"keyword_count": 3,
"url_slug": "seo-strategy",
"published": false,
"importance": 95.1,
"priority_category": "High",
"serp_position": null,
"serp_all_positions": [],
"aio_status": "not_present",
"aimode_status": "N/A",
"chatgpt_status": "N/A"
}
],
"created_at": "2026-01-20T12:00:00Z",
"updated_at": "2026-02-18T16:00:00Z"
}

Hierarchy node fields:

FieldTypeDescription
node_idUUIDUnique identifier for this topic node
namestringTopic name (reflects any renames from the Organizer)
typestringHierarchy level: PILLAR, HUB, BRANCH, or RESOURCE. Architecture nodes use uppercase; resource nodes use lowercase.
sourcestringNode origin: "architecture" (site architecture pages) or "resources" (topical map content)
parent_idUUID or nullParent node ID for building tree structures. null for root-level pillars.
mtstringMain Topic (level 1)
st2stringSubtopic 2 (level 2)
st3stringSubtopic 3 (level 3)
st4stringSubtopic 4 (level 4)
keywordsstring[]All keywords in this topic cluster
keyword_countintegerNumber of keywords in this cluster
url_slugstringSuggested URL slug for the centroid keyword
publishedbooleanWhether content has been published for this topic
importancefloatImportance score (0 to 100) based on topical authority analysis. Matches the score shown in the Floyi dashboard.
priority_categorystringPriority bucket: High, Medium, or Low
serp_positioninteger or nullYour brand’s best SERP ranking position (1-based) for this topic. null if not ranking.
serp_all_positionsinteger[]All SERP positions where your brand ranks for this topic
aio_statusstringYour brand’s presence in Google AI Overviews: cited, mentioned, not_present, or N/A (not tracked)
aimode_statusstringYour brand’s presence in Google AI Mode: mentioned_cited, cited, mentioned, not_present, or N/A
chatgpt_statusstringYour brand’s presence in ChatGPT Search: mentioned_cited, cited, mentioned, not_present, or N/A

[!TIP] Building a tree: Use parent_id to build parent-child relationships. Alternatively, group nodes by mt (pillars), then st2 (hubs), then st3 (branches), then st4 (resources).

Filtering by source: Add ?source=architecture or ?source=resources to return only nodes of that type. Without this parameter, both sources are returned.

AI presence statuses: cited means your URL appears in source links, mentioned means your brand name appears in the AI-generated text, mentioned_cited means both, not_present means the AI response exists but your brand is absent, and N/A means tracking has not been enabled or no AI response has been captured for this topic.

GET /api/v1/authority/{brand_id}/serp-data/{node_id}/

Returns all stored SERP (Search Engine Results Page) results for a specific topic node. Use this to see which competitor pages rank for a topic before generating a brief. The node_id comes from the hierarchy response above.

[!NOTE] This endpoint returns all stored SERP data without filtering. Your AI agent or workflow should select which competitors are most relevant for the brief.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../serp-data/f1a2b3c4-.../

Response:

{
"node_id": "f1a2b3c4-...",
"keyword": "best keyword research tools",
"serp_results": [
{
"position": 1,
"url": "https://ahrefs.com/blog/keyword-research-tools/",
"title": "12 Best Keyword Research Tools (Free & Paid)",
"snippet": "We tested and reviewed the best keyword research tools..."
},
{
"position": 2,
"url": "https://backlinko.com/best-keyword-research-tools",
"title": "Best Keyword Research Tools in 2026",
"snippet": "A hands-on comparison of the top keyword tools..."
}
],
"total_results": 10,
"serp_updated_at": "2026-02-15T12:00:00Z",
"snapshot_date": "2026-02-15"
}

SERP result fields:

FieldTypeDescription
positionintegerRank position in Google search results
urlstringURL of the ranking page
titlestringPage title from the SERP
snippetstringDescription snippet from the SERP

Error responses:

StatusCause
404 Not FoundNode not found in the hierarchy, or no SERP data available for this node
PATCH /api/v1/authority/{brand_id}/nodes/{node_id}/published/

Scope required: authority:write

Marks a topic node as published or unpublished. This updates the topical authority coverage tracking. Use this after you publish content for a topic to keep your authority metrics accurate.

Request body:

{
"published": true
}

Required fields: published (boolean)

Terminal window
curl -X PATCH \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"published": true}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../nodes/f1a2b3c4-.../published/

Response:

{
"node_id": "f1a2b3c4-...",
"published": true,
"message": "Published status updated."
}

After updating, Floyi automatically recalculates coverage rollups for the topical authority view.

Error responses:

StatusCause
400 Bad RequestInvalid node_id format (must be a valid UUID) or missing published field
404 Not FoundMap not found or you do not have access

Scope required: authority:read (GET), authority:write (POST, DELETE)

Manage keywords (anchor texts) on individual nodes in the authority hierarchy. Keywords are used for internal linking anchor text suggestions. They come from three sources:

  • map — Synced automatically from the topical map clustering data. Cannot be deleted via API.
  • ai — Generated by AI (via the Floyi dashboard). Can be deleted.
  • user — Manually added via API, dashboard, or created by combine operations. Can be deleted.
GET /api/v1/authority/{brand_id}/nodes/{node_id}/keywords/

Returns all keywords for a specific node. Optionally filter by source.

ParameterInTypeRequiredDescription
brand_idpathUUIDYesThe brand (authority map) ID
node_idpathUUIDYesThe node ID
sourcequerystringNoFilter by source: map, ai, or user
Terminal window
# List all keywords for a node
curl -s "https://api.floyi.com/api/v1/authority/{brand_id}/nodes/{node_id}/keywords/" \
-H "X-API-Key: flk_your_key"
# Filter by source
curl -s "https://api.floyi.com/api/v1/authority/{brand_id}/nodes/{node_id}/keywords/?source=user" \
-H "X-API-Key: flk_your_key"

Response:

{
"_meta": { "description": "Lists all keywords (anchor texts) for a specific node..." },
"node_id": "a1b2c3d4-...",
"count": 5,
"keywords": [
{
"id": 142,
"keyword": "topical authority seo",
"source": "map",
"search_volume": 1200,
"cpc_value": "3.50",
"created_at": "2025-10-15T14:30:00Z"
},
{
"id": 143,
"keyword": "topic cluster strategy",
"source": "ai",
"search_volume": 880,
"cpc_value": "2.10",
"created_at": "2025-10-16T09:00:00Z"
},
{
"id": 150,
"keyword": "content hub planning",
"source": "user",
"search_volume": null,
"cpc_value": null,
"created_at": "2025-11-01T12:00:00Z"
}
]
}
POST /api/v1/authority/{brand_id}/nodes/{node_id}/keywords/

Add one or more keywords to a node. Supports comma-separated input for bulk adds. Keywords are normalized to lowercase. Duplicates (case-insensitive) are skipped and reported.

FieldTypeRequiredDescription
keywordsstringYesOne or more keywords, comma-separated (e.g. "seo tools, keyword research")
Terminal window
curl -s -X POST "https://api.floyi.com/api/v1/authority/{brand_id}/nodes/{node_id}/keywords/" \
-H "X-API-Key: flk_your_key" \
-H "Content-Type: application/json" \
-d '{"keywords": "seo tools, keyword research, serp analysis"}'

Response (201 Created):

{
"_meta": { "description": "Add one or more keywords to a node..." },
"node_id": "a1b2c3d4-...",
"created_count": 2,
"keywords": [
{
"id": 160,
"keyword": "seo tools",
"source": "user",
"search_volume": null,
"cpc_value": null,
"created_at": "2025-11-02T10:00:00Z"
},
{
"id": 161,
"keyword": "serp analysis",
"source": "user",
"search_volume": null,
"cpc_value": null,
"created_at": "2025-11-02T10:00:00Z"
}
],
"duplicates_skipped": [
{ "keyword": "keyword research", "existing_source": "map" }
]
}

[!NOTE] If all keywords already exist, the response is 409 Conflict with duplicates_skipped details.

Error responses:

StatusCause
400 Bad RequestMissing or empty keywords field
404 Not FoundMap not found or you do not have access
409 ConflictAll submitted keywords already exist on this node
DELETE /api/v1/authority/{brand_id}/nodes/{node_id}/keywords/{keyword_id}/

Delete a keyword by its ID. User-added, AI-generated, and combine-created keywords can all be deleted. Only original map-sourced keywords (synced from clustering data) are protected.

ParameterInTypeRequiredDescription
brand_idpathUUIDYesThe brand (authority map) ID
node_idpathUUIDYesThe node ID
keyword_idpathintegerYesThe keyword ID (from the id field in list response)
Terminal window
curl -s -X DELETE "https://api.floyi.com/api/v1/authority/{brand_id}/nodes/{node_id}/keywords/160/" \
-H "X-API-Key: flk_your_key"

Response:

{
"_meta": { "description": "Delete a keyword from a node by its ID..." },
"deleted": true,
"keyword_id": 160,
"keyword": "seo tools"
}

Error responses:

StatusCause
403 ForbiddenAttempted to delete a map-sourced keyword
404 Not FoundKeyword not found, or map/node not accessible

Scope required: authority:read (GET), authority:write (POST)

Authority briefs are linked to topics in your authority hierarchy. Unlike standalone briefs (which accept freeform query_text), authority briefs require a node_id from the hierarchy. The topic name, search intent, and content context are derived from the node automatically.

GET /api/v1/authority/{brand_id}/briefs/

Returns all authority-linked content briefs for a brand.

Query parameters:

ParameterTypeDescription
statusstringFilter by brief status (e.g., COMPLETE, PENDING)
searchstringSearch by topic/query text or generated title (case-insensitive)
Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../briefs/
# Filter by status
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/authority/a1b2c3d4-.../briefs/?status=COMPLETE"

Response:

{
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"results": [
{
"id": "b5c6d7e8-...",
"query_text": "best keyword research tools",
"brand_name": "Floyi",
"status": "COMPLETE",
"generated_title": "Best Keyword Research Tools in 2026",
"generated_meta_description": "Discover the top keyword research tools...",
"created_at": "2026-02-10T08:00:00Z",
"updated_at": "2026-02-10T08:15:00Z"
}
]
}
GET /api/v1/authority/{brand_id}/briefs/{id}/

Returns the full brief including result_json, curated_brief_json, input_params, and topic_node linkage to the authority hierarchy.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../briefs/b5c6d7e8-.../

Response:

{
"id": "b5c6d7e8-...",
"query_text": "best keyword research tools",
"brand_name": "Floyi",
"status": "COMPLETE",
"generated_title": "Best Keyword Research Tools in 2026",
"generated_meta_description": "Discover the top keyword research tools...",
"result_json": { ... },
"curated_brief_json": { ... },
"input_params": { ... },
"topic_node": "f1a2b3c4-...",
"created_at": "2026-02-10T08:00:00Z",
"updated_at": "2026-02-10T08:15:00Z"
}

Detail-only fields:

FieldTypeDescription
result_jsonobjectThe raw brief output from the AI agent
curated_brief_jsonobjectThe user-edited version (if customized). null if no edits.
input_paramsobjectOriginal request parameters including node_id, brand_id, selected_serp_data
topic_nodeUUIDThe authority hierarchy node this brief is linked to
GET /api/v1/authority/{brand_id}/briefs/{id}/status/

Returns just the status of an authority brief. Useful for polling during generation.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../briefs/b5c6d7e8-.../status/

Response:

{
"id": "b5c6d7e8-...",
"status": "COMPLETE",
"query_text": "best keyword research tools",
"generated_title": "Best Keyword Research Tools in 2026",
"topic_node": "f1a2b3c4-..."
}
POST /api/v1/authority/{brand_id}/briefs/generate/

Triggers content brief generation for a topic from the authority hierarchy. The topic must exist in the brand’s hierarchy — use GET /api/v1/authority/{brand_id}/ to browse available topics and get node_id values.

Returns immediately with a 202 Accepted response. Poll the status endpoint for progress.

Request body:

{
"node_id": "f1a2b3c4-...",
"ai_model_id": "gpt-5-mini"
}

Required fields: node_id

Optional fields:

FieldTypeDescription
selected_serp_dataobject[]SERP competitor pages to analyze (max 15, each must include url). Auto-fetched from node’s stored SERP data if omitted.
user_provided_keywordsstring[]Additional keywords to include in the brief
internal_link_suggestionsobject[]Internal links to suggest (each: url, anchor_text)
ai_model_idstringAI model to use (e.g. "gpt-5-mini"). Uses default if not specified.

[!TIP] How it works: First call GET /api/v1/authority/{brand_id}/ to get the topic hierarchy. Pick a topic and use its node_id in the generate request. The API automatically derives the topic name, search intent, and content context from the hierarchy node. If selected_serp_data is omitted, SERP data is auto-fetched from the node’s stored data.

[!TIP] Use GET /api/v1/authority/{brand_id}/serp-data/{node_id}/ to preview available SERP data before generating a brief, so you or your AI agent can choose which competitors to include.

Terminal window
# Minimal (topic name, SERP data, and context all derived from the node)
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"node_id": "f1a2b3c4-..."}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../briefs/generate/
# With custom SERP data (you choose which competitors to analyze)
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{
"node_id": "f1a2b3c4-...",
"selected_serp_data": [
{"url": "https://example.com", "title": "Example", "snippet": "..."}
]
}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../briefs/generate/

Response (202 Accepted):

{
"id": "b5c6d7e8-...",
"status": "PENDING",
"query_text": "best keyword research tools",
"brand_name": "Floyi",
"node_id": "f1a2b3c4-...",
"message": "Brief generation started. Poll /api/v1/authority/{brand_id}/briefs/{id}/status/ for progress."
}

[!TIP] After generating, poll GET /api/v1/authority/{brand_id}/briefs/{id}/status/ every 10-15 seconds until the status changes to COMPLETE. Brief generation typically takes 1-3 minutes.

Error responses:

StatusCause
400 Bad RequestValidation error (SERP entry missing url, or no SERP data available)
402 Payment RequiredInsufficient credits
404 Not FoundBrand not found, node not found in hierarchy, or no hierarchy exists

404 — Node not in hierarchy:

{
"detail": "Topic node not found in the current authority hierarchy. Use GET /api/v1/authority/{brand_id}/ to browse valid topics."
}

400 — No SERP data available:

{
"detail": "No SERP data available for this topic. Please provide selected_serp_data or ensure SERP data has been collected for this topic in the topical map."
}

Scope required: authority:read (GET), authority:write (POST)

Authority articles are linked to topics in your authority hierarchy via topic_node. Unlike standalone articles, authority articles are created from authority briefs and maintain the hierarchy linkage throughout the workflow.

GET /api/v1/authority/{brand_id}/articles/

Returns all authority-linked articles for a brand.

Query parameters:

ParameterTypeDescription
searchstringSearch by article title (case-insensitive)
Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../articles/

Response:

{
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"results": [
{
"id": "c7d8e9f0-...",
"title": "Best Keyword Research Tools in 2026",
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"topic_node": "f1a2b3c4-...",
"machine_state": "draft_done",
"editorial_state": "draft",
"created_at": "2026-02-12T09:00:00Z",
"updated_at": "2026-02-14T11:00:00Z"
}
]
}
GET /api/v1/authority/{brand_id}/articles/{id}/

Returns the full article including brief reference, topic_node linkage, and all draft sections with their content.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../articles/c7d8e9f0-.../

Response:

{
"id": "c7d8e9f0-...",
"title": "Best Keyword Research Tools in 2026",
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"brief_id": "b5c6d7e8-...",
"topic_node": "f1a2b3c4-...",
"machine_state": "draft_done",
"editorial_state": "draft",
"additional_directions": null,
"sections": [
{
"id": "d1e2f3a4-...",
"position": 0,
"heading": "Introduction",
"status": "approved",
"ai_draft": "Keyword research is the foundation of any successful SEO strategy...",
"word_count_target": 200
},
{
"id": "e2f3a4b5-...",
"position": 1,
"heading": "Top Keyword Research Tools Compared",
"status": "approved",
"ai_draft": "Here are the best keyword research tools for 2026...",
"word_count_target": 800
}
],
"created_at": "2026-02-12T09:00:00Z",
"updated_at": "2026-02-14T11:00:00Z"
}

Section fields:

FieldTypeDescription
idUUIDSection identifier
positionintegerOrder position (0-based)
headingstringSection heading
statusstringDraft status: not_started, drafting, approved, needs_attention
ai_draftstring or nullThe AI-generated draft content for this section
word_count_targetinteger or nullTarget word count for this section
GET /api/v1/authority/{brand_id}/articles/{id}/status/

Returns generation progress including section-level status.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../articles/c7d8e9f0-.../status/

Response:

{
"id": "c7d8e9f0-...",
"machine_state": "in_progress",
"topic_node": "f1a2b3c4-...",
"sections_total": 8,
"sections_approved": 3,
"sections_drafting": 2,
"sections_not_started": 3,
"sections_needs_attention": 0,
"completion_percentage": 37.5,
"specialists_running": true,
"specialists_complete": false
}

Generate Authority Article Draft from Brief

Section titled “Generate Authority Article Draft from Brief”
POST /api/v1/authority/{brand_id}/articles/generate/

Creates a new article from a completed authority brief and immediately starts AI draft generation — one step instead of two. The brief must be in COMPLETE or PARTIAL_COMPLETE status, must be an authority brief (not standalone), and must have generated sections. The article inherits the topic_node linkage from the brief.

Request body:

{
"brief_id": "b5c6d7e8-...",
"ai_model_id": "claude-sonnet-4",
"intent": "human",
"specialists": {
"web_research": true,
"fact_check": true,
"intro_key_takeaways": true,
"web_research_mode": "basic"
}
}

Required fields: brief_id, ai_model_id

Optional fields: intent, specialists (same options as standalone article generation)

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"brief_id": "b5c6d7e8-...", "ai_model_id": "claude-sonnet-4"}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../articles/generate/

Response (202 Accepted):

{
"id": "c7d8e9f0-...",
"brief_id": "b5c6d7e8-...",
"title": "Best Keyword Research Tools in 2026",
"topic_node": "f1a2b3c4-...",
"task_id": "e1f2a3b4-...",
"status": "generating",
"message": "Article created and draft generation started. Poll /api/v1/authority/{brand_id}/articles/{id}/status/ for progress."
}

[!TIP] After triggering generation, poll GET /api/v1/authority/{brand_id}/articles/{id}/status/ every 15-30 seconds. Draft generation typically takes 3-10 minutes depending on sections and specialists enabled.

Error responses:

StatusCause
400 Bad Requestbrief_id or ai_model_id missing, brief not complete, brief is not an authority brief, or brief has no sections
402 Payment RequiredInsufficient credits for draft or specialist agents
404 Not FoundBrief or brand not found, or you do not have access
POST /api/v1/authority/{brand_id}/articles/{id}/generate/

Regenerates draft for an existing authority article. Creates a new version, re-syncs sections from the brief, resets all sections, and generates fresh content. Optionally accepts a different brief_id to switch briefs (must also be an authority brief). The topic_node linkage is updated if the new brief has a different node.

Request body:

{
"ai_model_id": "claude-sonnet-4",
"brief_id": "b5c6d7e8-...",
"intent": "human",
"specialists": {
"web_research": true,
"fact_check": true,
"intro_key_takeaways": true,
"web_research_mode": "basic"
}
}

Required fields: ai_model_id

Optional fields: brief_id (switch to a different authority brief), intent, specialists

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"ai_model_id": "claude-sonnet-4"}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../articles/c7d8e9f0-.../generate/

Response (202 Accepted):

{
"id": "c7d8e9f0-...",
"brief_id": "b5c6d7e8-...",
"title": "Best Keyword Research Tools in 2026",
"topic_node": "f1a2b3c4-...",
"task_id": "e1f2a3b4-...",
"status": "regenerating",
"message": "Draft regeneration started. Poll /api/v1/authority/{brand_id}/articles/{id}/status/ for progress."
}

Error responses:

StatusCause
400 Bad RequestMissing ai_model_id
402 Payment RequiredInsufficient credits for draft or specialist agents
409 ConflictArticle generation already in progress

Scope required: user:read

GET /api/v1/me/profile/

Returns the authenticated user’s profile.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/me/profile/

Response:

{
"uuid": "e1f2a3b4-...",
"email": "user@example.com",
"first_name": "Jane",
"last_name": "Doe",
"subscription_plan": "Agency Plan",
"subscription_interval": "monthly",
"account_status": "active",
"date_joined": "2025-06-01T00:00:00Z",
"last_active": "2026-02-21T09:30:00Z"
}
GET /api/v1/me/credits/

Returns your current credit balance across all credit types.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/me/credits/

Response:

{
"free_credits": 0,
"monthly_credits": 450,
"payg_credits": 100,
"total_credits": 550,
"monthly_credits_last_reset": "2026-02-01T00:00:00Z",
"subscription_renewal_date": "2026-03-01T00:00:00Z"
}
GET /api/v1/me/teams/

Returns all teams you are an active member of. Use the team id as the X-Team-ID header value to access that team’s workspace data (see Workspace Selection).

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/me/teams/

Response:

{
"_meta": { "description": "Lists all teams the authenticated user is an active member of..." },
"results": [
{
"team": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Acme Marketing",
"slug": "acme-marketing",
"plan_name": "Agency Plan",
"created_at": "2025-09-15T10:00:00Z"
},
"role": "owner",
"status": "active"
}
]
}

Response fields:

FieldDescription
team.idThe team UUID — use this as the X-Team-ID header value
team.nameDisplay name of the team
team.slugURL-friendly team identifier
roleYour role in this team: owner, admin, or member
statusMembership status (always active in this response)

The Clustering Tool lets you cluster any set of keywords by SERP URL overlap — no brand required. It fetches SERP data for each keyword, then groups keywords that share similar search results.

Scope: clustering:read (read), clustering:write (write)

GET /api/v1/clustering/

Returns all standalone clustering reports.

Terminal window
curl -H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/clustering/
GET /api/v1/clustering/{id}/

Returns full report with cluster results, keyword metrics, and SERP data timestamps.

Terminal window
curl -H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/clustering/{id}/
GET /api/v1/clustering/{id}/status/

Polls the progress of a clustering task. Returns task state, progress percentage, and message.

Terminal window
curl -H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/clustering/{id}/status/

Response:

{
"_meta": { "description": "..." },
"id": "abc-123",
"status": "in_progress",
"state": "PENDING",
"progress": 45,
"message": "Fetching SERPs and clustering in progress..."
}
GET /api/v1/clustering/{id}/serp-data/?keyword=seo+tools

Returns stored SERP results for a specific keyword within a clustering report. Does not trigger live scraping.

Terminal window
curl -H "X-API-Key: fyi_live_your_key" \
"https://api.floyi.com/api/v1/clustering/{id}/serp-data/?keyword=seo+tools"
POST /api/v1/clustering/

Creates a new clustering report and starts SERP-based keyword clustering. Costs credits based on keyword count. Poll GET /clustering/{id}/status/ for progress.

Request body:

FieldTypeRequiredDescription
report_namestringYesName for this clustering report
keywordsstring[]YesList of keywords to cluster (max 10,000)
countrystringNoCountry code for SERP data (default: "us")
locationstringNoLocation for SERP data (e.g. "New York, NY")
languagestringNoLanguage code (default: "en")
overlap_percentagefloatNoURL overlap threshold 0.2-0.9 (default: 0.4)
ai_model_idstringNoAI model to use (uses default if omitted)
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"report_name": "SEO Tools Cluster",
"keywords": ["seo tools", "keyword research", "backlink checker", "rank tracker"],
"country": "us",
"overlap_percentage": 0.4
}' \
https://api.floyi.com/api/v1/clustering/

Response (202):

{
"_meta": { "description": "..." },
"id": "abc-123",
"report_name": "SEO Tools Cluster",
"status": "in_progress",
"task_id": "celery-task-id",
"group_id": "group-uuid",
"total_batches": 1,
"total_keywords": 4,
"message": "Clustering started. Poll /api/v1/clustering/{id}/status/ for progress."
}

Errors:

StatusMeaning
400No valid keywords provided
402Insufficient credits
POST /api/v1/clustering/{id}/recluster/

Re-clusters keywords using existing SERP data with a new overlap percentage. No new SERP fetching, so no additional credit cost for SERPs.

Request body:

FieldTypeRequiredDescription
overlap_percentagefloatYesNew overlap threshold 0.2-0.9
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key" \
-H "Content-Type: application/json" \
-d '{"overlap_percentage": 0.6}' \
https://api.floyi.com/api/v1/clustering/{id}/recluster/

Errors:

StatusMeaning
404Report not found
409Clustering already in progress
DELETE /api/v1/clustering/{id}/

Permanently deletes a clustering report and all associated SERP data.

Terminal window
curl -X DELETE \
-H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/clustering/{id}/

Returns 204 No Content on success.


Authority Clustering is the brand-tied version. Keywords are automatically extracted from the brand’s topical research hierarchy — you don’t provide them manually. Results feed into the topical map generation pipeline.

Scope: clustering:read (read), clustering:write (write)

GET /api/v1/authority/{brand_id}/clustering/

Returns the most recent clustering results for a brand, including cluster centroids, keyword associations, and metrics.

Terminal window
curl -H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/authority/{brand_id}/clustering/
GET /api/v1/authority/{brand_id}/clustering/status/

Polls the progress of a brand clustering task.

Terminal window
curl -H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/authority/{brand_id}/clustering/status/
GET /api/v1/authority/{brand_id}/clustering/serp-data/?keyword=seo+tools

Returns stored SERP results for a keyword from the brand’s clustering data.

Terminal window
curl -H "X-API-Key: fyi_live_your_key" \
"https://api.floyi.com/api/v1/authority/{brand_id}/clustering/serp-data/?keyword=seo+tools"
POST /api/v1/authority/{brand_id}/clustering/start/

Starts SERP-based keyword clustering for a brand. Keywords are automatically extracted from the brand’s topical research. Costs credits based on keyword count. Poll GET /authority/{brand_id}/clustering/status/ for progress.

Request body:

FieldTypeRequiredDescription
countrystringNoCountry code for SERP data (default: "us")
locationstringNoLocation for SERP data
languagestringNoLanguage code (default: "en")
overlap_percentagefloatNoURL overlap threshold 0.2-0.9 (default: 0.4)
ai_model_idstringNoAI model to use
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key" \
-H "Content-Type: application/json" \
-d '{"country": "us", "overlap_percentage": 0.4}' \
https://api.floyi.com/api/v1/authority/{brand_id}/clustering/start/

Response (202):

{
"_meta": { "description": "..." },
"brand_id": "abc-123",
"status": "in_progress",
"task_id": "celery-task-id",
"group_id": "group-uuid",
"total_batches": 3,
"total_keywords": 250,
"message": "Clustering started. Poll /api/v1/authority/{brand_id}/clustering/status/ for progress."
}

Errors:

StatusMeaning
400No keywords found in topical research
402Insufficient credits
404Brand not found
409Clustering already in progress
POST /api/v1/authority/{brand_id}/clustering/recluster/

Re-clusters a brand’s keywords using existing SERP data with a new overlap percentage.

Request body:

FieldTypeRequiredDescription
overlap_percentagefloatYesNew overlap threshold 0.2-0.9
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key" \
-H "Content-Type: application/json" \
-d '{"overlap_percentage": 0.6}' \
https://api.floyi.com/api/v1/authority/{brand_id}/clustering/recluster/

Errors:

StatusMeaning
404Brand or clustering results not found
409Clustering already in progress

The Images API lets you analyze article content for optimal image placements, generate images using AI models, and retrieve the results. Images are scoped to individual articles.

Scope: content:read (read), content:write (write)

GET /api/v1/content/articles/{article_id}/images/

Returns all generated images for an article, including URLs, prompts, and placement metadata.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/content/articles/a1b2c3d4-.../images/

Response:

{
"article_id": "a1b2c3d4-...",
"images": [
{
"id": "e5f6a7b8-...",
"image_url": "https://cdn.example.com/images/generated-image.png",
"alt_text": "Keyword research dashboard comparison",
"anchor_heading": "Top Keyword Research Tools Compared",
"prompt": "A clean, modern dashboard showing keyword research metrics...",
"model_used": "dall-e-3",
"inserted": true,
"created_at": "2026-03-15T10:30:00Z"
}
],
"free_images_remaining": 0
}

Image fields:

FieldTypeDescription
idUUIDImage identifier
image_urlstringURL of the generated image
alt_textstringAlt text for the image
anchor_headingstringThe article heading where the image is placed
promptstringThe prompt used to generate the image
model_usedstringThe AI model that generated the image
insertedbooleanWhether the image has been inserted into the article
created_atdatetimeWhen the image was generated
GET /api/v1/content/articles/{article_id}/images/models/

Returns available image generation models with capabilities, supported sizes, and credit costs.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/content/articles/a1b2c3d4-.../images/models/

Response:

{
"models": [
{
"model_id": "dall-e-3",
"display_name": "DALL-E 3",
"api_format": "openai",
"family": "dall-e",
"supported_sizes": ["1024x1024", "1792x1024", "1024x1792"],
"default_size": "1024x1024",
"supported_aspect_ratios": ["1:1", "16:9", "9:16"],
"credit_cost": 2
}
]
}
POST /api/v1/content/articles/{article_id}/images/analyze/

Analyzes the article’s draft content and returns suggested image placements with AI-generated prompts. No credits are charged for analysis. The article must have generated draft content.

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/content/articles/a1b2c3d4-.../images/analyze/

Response:

{
"placements": [
{
"anchor_heading": "Top Keyword Research Tools Compared",
"prompt": "A clean, modern dashboard showing keyword research metrics and competitor analysis...",
"alt_text": "Keyword research dashboard comparison",
"reasoning": "This section compares multiple tools — a visual comparison would help readers."
}
],
"free_images_remaining": 1
}
POST /api/v1/content/articles/{article_id}/images/generate/

Generates images for selected placements via a background task. The first image per article is free; additional images cost credits based on the model. Use the analyze endpoint first to get placement suggestions with prompts.

Request body:

{
"placements": [
{
"anchor_heading": "Top Keyword Research Tools Compared",
"prompt": "A clean, modern dashboard showing keyword research metrics...",
"model_id": "dall-e-3",
"size_params": { "width": 1024, "height": 1024 },
"alt_text": "Keyword research dashboard comparison"
}
]
}
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"placements": [{"anchor_heading": "Top Tools", "prompt": "...", "model_id": "dall-e-3", "size_params": {"width": 1024, "height": 1024}, "alt_text": "..."}]}' \
https://api.floyi.com/api/v1/content/articles/a1b2c3d4-.../images/generate/

Response (202 Accepted):

{
"task_id": "abc123-...",
"article_id": "a1b2c3d4-...",
"placement_count": 1,
"free_images_used": 1,
"paid_images": 0,
"credit_cost": 0,
"message": "Image generation started. Poll .../images/status/?task_id=abc123-... for progress."
}

Errors:

StatusMeaning
400No placements provided or unknown image model
402Insufficient credits for paid images
404Article not found
GET /api/v1/content/articles/{article_id}/images/status/?task_id={task_id}

Polls the background image generation task. Returns status and progress information.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/content/articles/a1b2c3d4-.../images/status/?task_id=abc123-..."

Response:

{
"task_id": "abc123-...",
"state": "SUCCESS",
"status": "completed",
"message": "Image generation completed.",
"result": { "images_generated": 1, "images_failed": 0 }
}

The WordPress API lets you publish articles directly to WordPress sites, manage site connections, and track publishing history. Publishing runs as a background task.

Scope: content:read (read), content:write (write)

GET /api/v1/cms/wordpress/connections/

Returns all WordPress site connections for the current workspace, including status, capabilities, and detected SEO plugin.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/cms/wordpress/connections/

Response:

{
"results": [
{
"id": "c1d2e3f4-...",
"site_name": "My Blog",
"site_url": "https://myblog.com",
"status": "active",
"capabilities": { "posts": true, "pages": true, "media": true },
"seo_plugin_slug": "yoast-seo",
"seo_plugin_version": "22.1",
"created_at": "2026-02-01T12:00:00Z"
}
]
}
GET /api/v1/cms/wordpress/publish-records/

Returns WordPress publish records showing what has been published, where, and when. Filter by article or connection.

Query parameters: ?article_id= ?connection_id=

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/cms/wordpress/publish-records/?article_id=a1b2c3d4-..."

Response:

{
"results": [
{
"id": 42,
"article_id": "a1b2c3d4-...",
"article_title": "Best Keyword Research Tools in 2026",
"site_name": "My Blog",
"site_url": "https://myblog.com",
"wp_post_id": 1234,
"wp_post_type": "post",
"wp_permalink": "https://myblog.com/best-keyword-research-tools/",
"wp_status": "publish",
"last_published_at": "2026-03-20T14:00:00Z",
"last_sync_at": "2026-03-20T14:00:00Z",
"needs_update": false,
"published_title": "Best Keyword Research Tools in 2026",
"published_slug": "best-keyword-research-tools",
"created_at": "2026-03-20T14:00:00Z",
"updated_at": "2026-03-20T14:00:00Z"
}
]
}
POST /api/v1/cms/wordpress/publish/

Publishes a single article to a WordPress site. The publish runs as a background task — use the returned task_id to poll for completion.

Request body:

{
"article_id": "a1b2c3d4-...",
"site_connection_id": "c1d2e3f4-...",
"status": "draft",
"post_type": "post",
"categories": [1, 2],
"tags": [5],
"seo_title": "Best Keyword Research Tools | Floyi",
"seo_description": "Compare the top keyword research tools for 2026...",
"include_schema": true
}

Required fields: article_id, site_connection_id

Optional fields: status (default "draft"), post_type (default "post"), categories, tags, author_id, slug, seo_title, seo_description, seo_focus_keyword, include_schema, scheduled_date

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"article_id": "a1b2c3d4-...", "site_connection_id": "c1d2e3f4-...", "status": "draft"}' \
https://api.floyi.com/api/v1/cms/wordpress/publish/

Response (202 Accepted):

{
"task_id": "wp-task-123-...",
"article_id": "a1b2c3d4-...",
"site_connection_id": "c1d2e3f4-...",
"message": "Publishing task queued. Poll .../task-status/?task_id=wp-task-123-... for progress."
}

Errors:

StatusMeaning
400Invalid request data or WordPress connection not active
404Article or WordPress connection not found
POST /api/v1/cms/wordpress/bulk-publish/

Publishes up to 50 articles in a single request. Each article can target a different WordPress connection with its own publish settings. Runs as a single background task.

Request body:

{
"articles": [
{
"article_id": "a1b2c3d4-...",
"site_connection_id": "c1d2e3f4-...",
"status": "draft"
},
{
"article_id": "b2c3d4e5-...",
"site_connection_id": "c1d2e3f4-...",
"status": "publish"
}
]
}
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"articles": [{"article_id": "a1b2c3d4-...", "site_connection_id": "c1d2e3f4-...", "status": "draft"}]}' \
https://api.floyi.com/api/v1/cms/wordpress/bulk-publish/

Response (202 Accepted):

{
"task_id": "wp-bulk-456-...",
"article_count": 2,
"message": "Bulk publishing 2 articles. Poll .../task-status/?task_id=wp-bulk-456-... for progress."
}
GET /api/v1/cms/wordpress/task-status/?task_id={task_id}

Polls the status of a publish or bulk-publish background task.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/cms/wordpress/task-status/?task_id=wp-task-123-..."

Response:

{
"task_id": "wp-task-123-...",
"state": "SUCCESS",
"status": "completed",
"message": "Publishing completed.",
"result": { "wp_post_id": 1234, "wp_permalink": "https://myblog.com/best-keyword-research-tools/" }
}

The Content Guide API lets you manage brand content guidelines — terminology rules, compliance policies, competitor mention policies, brand messaging rules, and boilerplate snippets. You can also trigger AI-powered generation of an entire content guide from brand profile data.

Scope: content:read (read), content:write (write)

GET /api/v1/content-guide/{brand_id}/

Returns all active content guide entries across all five categories for a brand.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/content-guide/a1b2c3d4-.../

Response:

{
"brand_id": "a1b2c3d4-...",
"brand_name": "Floyi",
"terminology": [
{
"id": 1,
"term": "SEO tool",
"preferred_term": "content strategy platform",
"severity": "discouraged",
"note": "We position as a strategy platform, not a tool.",
"is_active": true,
"priority": 1,
"created_at": "2026-03-01T10:00:00Z",
"updated_at": "2026-03-01T10:00:00Z"
}
],
"compliance": [
{
"id": 1,
"name": "Health Claims Policy",
"rules_json": {
"banned_claims": ["guaranteed results"],
"required_disclosures": ["Results may vary"]
},
"is_active": true,
"priority": 1,
"created_at": "2026-03-01T10:00:00Z",
"updated_at": "2026-03-01T10:00:00Z"
}
],
"competitor_policies": [
{
"id": 1,
"competitor_name": "Clearscope",
"mention_policy": "neutral",
"comparison_notes": "Acknowledge strengths but highlight our closed-loop workflow.",
"is_active": true,
"priority": 1,
"created_at": "2026-03-01T10:00:00Z",
"updated_at": "2026-03-01T10:00:00Z"
}
],
"brand_messaging": [
{
"id": 1,
"rule_type": "messaging_pillar",
"content": "Topic-first strategy replaces the disconnected tool stack.",
"is_active": true,
"priority": 1,
"created_at": "2026-03-01T10:00:00Z",
"updated_at": "2026-03-01T10:00:00Z"
}
],
"boilerplate": [
{
"id": 1,
"snippet_type": "about",
"name": "Company About",
"content": "Floyi is a topic-first content strategy platform...",
"is_active": true,
"created_at": "2026-03-01T10:00:00Z",
"updated_at": "2026-03-01T10:00:00Z"
}
]
}
GET /api/v1/content-guide/{brand_id}/summary/

Returns entry counts per category without the full data. Useful for dashboards and status checks.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/content-guide/a1b2c3d4-.../summary/

Response:

{
"brand_id": "a1b2c3d4-...",
"counts": {
"terminology": 12,
"compliance": 3,
"competitor_policies": 5,
"brand_messaging": 8,
"boilerplate": 4
},
"total": 32,
"is_empty": false
}
POST /api/v1/content-guide/{brand_id}/terminology/

Adds a terminology/lexicon entry to the content guide. Terminology entries define preferred terms and discouraged alternatives.

Request body:

{
"term": "SEO tool",
"preferred_term": "content strategy platform",
"severity": "discouraged",
"note": "We position as a strategy platform, not a tool."
}
FieldTypeRequiredDescription
termstringyesThe term to control
preferred_termstringyesThe preferred alternative
severitystringno"discouraged", "banned", or "preferred"
notestringnoExplanation for writers
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"term": "SEO tool", "preferred_term": "content strategy platform", "severity": "discouraged"}' \
https://api.floyi.com/api/v1/content-guide/a1b2c3d4-.../terminology/

Returns 201 Created with the new entry.

POST /api/v1/content-guide/{brand_id}/compliance/

Adds a compliance rule set. Each rule set has a name and a rules_json object containing banned_claims and required_disclosures arrays.

Request body:

{
"name": "Health Claims Policy",
"rules_json": {
"banned_claims": ["guaranteed results", "instant rankings"],
"required_disclosures": ["Results may vary based on industry"]
}
}
POST /api/v1/content-guide/{brand_id}/competitor-policy/

Defines how a competitor should be referenced in content.

Request body:

{
"competitor_name": "Clearscope",
"mention_policy": "neutral",
"comparison_notes": "Acknowledge strengths but highlight our closed-loop workflow."
}
FieldTypeRequiredDescription
competitor_namestringyesName of the competitor
mention_policystringno"neutral", "positive", "avoid", or "compare"
comparison_notesstringnoGuidance for writers when comparing
POST /api/v1/content-guide/{brand_id}/brand-messaging/

Adds a brand messaging rule (messaging pillar, tone directive, or key phrase).

Request body:

{
"rule_type": "messaging_pillar",
"content": "Topic-first strategy replaces the disconnected tool stack."
}
POST /api/v1/content-guide/{brand_id}/boilerplate/

Adds a pre-approved boilerplate snippet (about section, disclaimer, CTA, etc.).

Request body:

{
"snippet_type": "about",
"name": "Company About",
"content": "Floyi is a topic-first content strategy platform that takes you from brand strategy to published drafts in one system."
}
POST /api/v1/content-guide/{brand_id}/ai-generate/

Triggers AI-powered generation of a complete content guide based on the brand’s profile data (name, mission, voice, audience). The brand must have brand_name, mission, and brand_voice set. Costs credits. Returns a task_id for polling.

Request body (optional):

{
"ai_model_id": "gpt-5-mini"
}
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{}' \
https://api.floyi.com/api/v1/content-guide/a1b2c3d4-.../ai-generate/

Response (202 Accepted):

{
"task_id": "cg-gen-789-...",
"brand_id": "a1b2c3d4-...",
"message": "Content guide generation started. Poll .../ai-generate/status/?task_id=cg-gen-789-... for progress."
}

Errors:

StatusMeaning
400Brand missing required fields (brand_name, mission, brand_voice)
404Brand not found
GET /api/v1/content-guide/{brand_id}/ai-generate/status/?task_id={task_id}

Polls the AI content guide generation task. When complete, the response includes the full generated content_guide object.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
"https://api.floyi.com/api/v1/content-guide/a1b2c3d4-.../ai-generate/status/?task_id=cg-gen-789-..."

Response (completed):

{
"task_id": "cg-gen-789-...",
"state": "SUCCESS",
"status": "completed",
"message": "Content guide generation completed.",
"content_guide": {
"terminology": [...],
"compliance": [...],
"competitor_policies": [...],
"brand_messaging": [...],
"boilerplate": [...]
}
}
POST /api/v1/content-guide/{brand_id}/ai-generate/save/

Saves the AI-generated content guide entries to the brand. Pass the content_guide object received from the completed generation status response.

Request body:

{
"content_guide": {
"terminology": [
{ "term": "SEO tool", "preferred_term": "content strategy platform", "severity": "discouraged" }
],
"compliance": [
{ "name": "Claims Policy", "banned_claims": ["guaranteed results"], "required_disclosures": [] }
],
"competitor_policies": [
{ "competitor_name": "Clearscope", "mention_policy": "neutral", "comparison_notes": "..." }
],
"brand_messaging": [
{ "rule_type": "messaging_pillar", "content": "Topic-first strategy..." }
],
"boilerplate": [
{ "snippet_type": "about", "name": "Company About", "content": "..." }
]
}
}
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"content_guide": {"terminology": [...], "compliance": [...]}}' \
https://api.floyi.com/api/v1/content-guide/a1b2c3d4-.../ai-generate/save/

Response:

{
"success": true,
"counts": {
"terminology": 12,
"compliance": 3,
"competitor_policies": 5,
"brand_messaging": 8,
"boilerplate": 4
}
}

The Authority Organizer API lets you restructure the topical authority hierarchy — move, rename, combine, create, archive, and restore nodes. All operations are stored as overrides on top of the base topical map, so they can be cleared to reset back to the original structure.

The hierarchy follows a 4-level structure: Pillar > Hub > Branch > Resource. Node types are automatically recalculated when nodes are moved.

Scope: authority:read (read), authority:write (write)

GET /api/v1/authority/{brand_id}/organizer/overrides/

Returns all active hierarchy overrides for a brand’s authority map, including moves, renames, combines, creates, and archives.

Terminal window
curl -H "X-API-Key: fyi_live_your_key_here" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../organizer/overrides/

Response:

{
"brand_id": "a1b2c3d4-...",
"count": 3,
"overrides": [
{
"id": 1,
"node_id": "f1a2b3c4-...",
"override_type": "rename",
"original_name": "SEO Tools",
"new_name": "Keyword Research Tools",
"created_at": "2026-03-15T10:00:00Z"
},
{
"id": 2,
"node_id": "g2h3i4j5-...",
"override_type": "move",
"original_parent_id": "p1q2r3s4-...",
"new_parent_id": "t5u6v7w8-...",
"created_at": "2026-03-15T10:05:00Z"
},
{
"id": 3,
"node_id": "x9y0z1a2-...",
"override_type": "create",
"name": "AI Search Optimization",
"parent_id": "f1a2b3c4-...",
"created_at": "2026-03-16T08:00:00Z"
}
]
}
POST /api/v1/authority/{brand_id}/organizer/move/

Moves a node (and all its descendants) to a new parent. The node’s type (Pillar/Hub/Branch/Resource) is automatically recalculated based on its new depth. Set new_parent_id to null to make it a top-level Pillar.

Request body:

{
"node_id": "f1a2b3c4-...",
"new_parent_id": "t5u6v7w8-...",
"previous_parent_id": "p1q2r3s4-..."
}
FieldTypeRequiredDescription
node_idstringyesUUID of the node to move
new_parent_idstringnoUUID of the new parent (null for top-level)
previous_parent_idstringnoCurrent parent UUID (for audit trail)
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"node_id": "f1a2b3c4-...", "new_parent_id": "t5u6v7w8-..."}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../organizer/move/

Response:

{
"success": true,
"node_id": "f1a2b3c4-...",
"new_parent_id": "t5u6v7w8-...",
"message": "Node moved successfully."
}
POST /api/v1/authority/{brand_id}/organizer/rename/

Renames a node. The new name must be unique within the map (case-insensitive). Renaming also updates the node’s SERP tracking query.

Request body:

{
"node_id": "f1a2b3c4-...",
"new_name": "Keyword Research Tools",
"original_name": "SEO Tools"
}
FieldTypeRequiredDescription
node_idstringyesUUID of the node to rename
new_namestringyesNew name (must be unique in the map)
original_namestringnoCurrent name (for audit trail)
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"node_id": "f1a2b3c4-...", "new_name": "Keyword Research Tools"}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../organizer/rename/

Response:

{
"success": true,
"node_id": "f1a2b3c4-...",
"new_name": "Keyword Research Tools",
"message": "Node renamed successfully."
}

Errors:

StatusMeaning
404Authority map not found
409A node with that name already exists
POST /api/v1/authority/{brand_id}/organizer/combine/

Combines two or more nodes into one. The primary node survives; merged nodes are removed. Children of merged nodes are reparented to the primary. Names of merged nodes are added as keywords on the primary node. Cross-level combines are allowed, but the resulting hierarchy cannot exceed 4 levels.

Request body:

{
"primary_id": "f1a2b3c4-...",
"merged_ids": ["g2h3i4j5-...", "k6l7m8n9-..."],
"combined_name": "SEO & Keyword Tools",
"merged_names": ["Keyword Planners", "Search Tools"]
}
FieldTypeRequiredDescription
primary_idstringyesUUID of the surviving node
merged_idsstring[]yesUUIDs of nodes to merge into primary
combined_namestringnoNew name for the combined node (defaults to primary’s name)
merged_namesstring[]noNames of merged nodes (auto-resolved if omitted)
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"primary_id": "f1a2b3c4-...", "merged_ids": ["g2h3i4j5-..."]}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../organizer/combine/

Response:

{
"success": true,
"primary_id": "f1a2b3c4-...",
"merged_ids": ["g2h3i4j5-...", "k6l7m8n9-..."],
"combined_name": "SEO & Keyword Tools",
"merged_names_as_keywords": ["Keyword Planners", "Search Tools"],
"message": "Nodes combined successfully. Merged nodes removed; their children reparented to the primary node; their names added as keywords."
}

Errors:

StatusMeaning
400primary_id in merged_ids, or combine would exceed 4 hierarchy levels
404Authority map not found
POST /api/v1/authority/{brand_id}/organizer/create/

Creates a new node in the hierarchy. The node type (Pillar/Hub/Branch/Resource) is automatically determined by its depth. Omit parent_id to create a top-level Pillar.

Request body:

{
"name": "AI Search Optimization",
"parent_id": "f1a2b3c4-..."
}
FieldTypeRequiredDescription
namestringyesName for the new node (must be unique)
parent_idstringnoParent node UUID (null for top-level Pillar)
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"name": "AI Search Optimization", "parent_id": "f1a2b3c4-..."}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../organizer/create/

Response (201 Created):

{
"success": true,
"node_id": "new-uuid-generated-...",
"name": "AI Search Optimization",
"parent_id": "f1a2b3c4-...",
"message": "Node created successfully."
}
POST /api/v1/authority/{brand_id}/organizer/archive/

Archives one or more nodes. Archived nodes are hidden from the effective hierarchy but can be restored later. No data is deleted.

Request body:

{
"node_ids": ["f1a2b3c4-...", "g2h3i4j5-..."]
}
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"node_ids": ["f1a2b3c4-..."]}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../organizer/archive/

Response:

{
"success": true,
"archived_node_ids": ["f1a2b3c4-...", "g2h3i4j5-..."],
"count": 2,
"message": "Archived 2 node(s)."
}
POST /api/v1/authority/{brand_id}/organizer/restore/

Restores previously archived nodes, making them visible in the hierarchy again.

Request body:

{
"node_ids": ["f1a2b3c4-..."]
}
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"node_ids": ["f1a2b3c4-..."]}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../organizer/restore/

Response:

{
"success": true,
"restored_node_ids": ["f1a2b3c4-..."],
"count": 1,
"message": "Restored 1 node(s)."
}
POST /api/v1/authority/{brand_id}/organizer/clear/

Resets hierarchy overrides back to the baseline topical map state. Pass specific node_ids to clear only those nodes, or omit to clear ALL overrides for the entire map. This action is irreversible.

Request body:

{
"node_ids": ["f1a2b3c4-..."]
}

Omit node_ids (or pass null) to clear all overrides:

{}
Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../organizer/clear/

Response:

{
"success": true,
"cleared_count": 5,
"message": "Cleared 5 override(s)."
}

Errors:

StatusMeaning
404Authority map not found

You can manage your API keys from the Settings > API Keys tab in Floyi or programmatically through the key management endpoints.

The API Keys tab shows all your keys with:

  • Name — The label you gave the key
  • Prefix — The first 12 characters (e.g., fyi_live_a3b...) for identification
  • Type — Integration or Developer
  • Status — Active or Revoked
  • Last Used — When the key was last used to make a request
  • Created — When the key was created

Revoking permanently deactivates a key. Any request using a revoked key will receive a 401 error.

  1. Find the key in the API Keys tab.
  2. Click the Revoke button (trash icon).
  3. Confirm the revocation.

Revocation is immediate and irreversible.

Rotating creates a new key with the same name, type, scopes, and settings as the old key, then revokes the old key. Use this to periodically refresh your keys without changing your configuration.

  1. Find the key in the API Keys tab.
  2. Click the Rotate button.
  3. Copy the new key immediately.

The old key stops working as soon as the new key is created.


Every request made to the /api/v1/ endpoints using an API key is logged automatically. Audit logs capture:

  • Endpoint path and HTTP method
  • Response status code
  • Client IP address
  • Response time in milliseconds
  • Timestamp

Use the audit log endpoint to view your request history, debug issues, and monitor for unauthorized access.

GET /api/v1/me/audit-logs/

Scope required: user:read

Returns a paginated list of API request logs for all of your API keys. Results are ordered by most recent first. Audit logs are retained for 90 days.

Query parameters:

ParameterTypeDescription
api_key_idUUIDFilter by a specific API key
methodstringFilter by HTTP method (GET, POST, PUT, DELETE)
status_codeintegerFilter by response status code (e.g., 200, 400, 429)
endpointstringFilter by endpoint path (partial match)
pageintegerPage number (default: 1)
page_sizeintegerResults per page (default: 50, max: 200)
Terminal window
# View recent audit logs
curl -H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/me/audit-logs/
# Filter by specific key and method
curl -H "X-API-Key: fyi_live_your_key" \
"https://api.floyi.com/api/v1/me/audit-logs/?api_key_id=a1b2c3d4-...&method=POST"
# Filter by status code (e.g., find failed requests)
curl -H "X-API-Key: fyi_live_your_key" \
"https://api.floyi.com/api/v1/me/audit-logs/?status_code=429&page_size=20"

Response:

{
"_meta": {
"description": "Paginated list of API request audit logs..."
},
"count": 342,
"next": "https://api.floyi.com/api/v1/me/audit-logs/?page=2",
"previous": null,
"results": [
{
"id": "e1f2a3b4-...",
"api_key_name": "My Integration Key",
"api_key_prefix": "fyi_live_a3b...",
"endpoint": "/api/v1/brands/",
"method": "GET",
"status_code": 200,
"ip_address": "203.0.113.42",
"response_time_ms": 45,
"timestamp": "2026-02-27T14:30:00Z"
},
{
"id": "d5c6b7a8-...",
"api_key_name": "My Integration Key",
"api_key_prefix": "fyi_live_a3b...",
"endpoint": "/api/v1/research/tr_abc123/tree/",
"method": "GET",
"status_code": 200,
"ip_address": "203.0.113.42",
"response_time_ms": 120,
"timestamp": "2026-02-27T14:29:55Z"
}
]
}

Response fields:

FieldDescription
countTotal number of matching audit log entries
nextURL for the next page (null if on the last page)
previousURL for the previous page (null if on the first page)
idUnique audit log entry ID
api_key_nameName of the API key that made the request
api_key_prefixPrefix of the API key (e.g., fyi_live_a3b...)
endpointThe API endpoint that was called
methodHTTP method (GET, POST, PUT, DELETE)
status_codeHTTP response status code
ip_addressClient IP address
response_time_msServer response time in milliseconds
timestampWhen the request was made (ISO 8601)

  • Store API keys in environment variables or a secrets manager. Never hardcode them.
  • Floyi stores only the SHA-256 hash of your key. The plaintext is shown once at creation and cannot be recovered.

IP allowlists can be configured for API keys. When set, requests from IPs not on the list receive a 401 error.

You can set an optional expiration date when creating a key. Expired keys automatically stop working. Use this for temporary access (e.g., contractor integrations or time-limited automations).

Rotate your API keys periodically, especially if they are used in shared environments. Floyi’s rotate feature makes this seamless — same settings, new key, old key revoked instantly.


AI Agent: Full Content Pipeline (Authority Flow)

Section titled “AI Agent: Full Content Pipeline (Authority Flow)”

An AI agent can automate your entire content workflow — from analyzing topic gaps to generating published drafts. This uses the authority endpoints so all briefs and articles are linked to your topical hierarchy.

Terminal window
# 1. Fetch the authority hierarchy to analyze coverage
curl -H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../
# 2. Get SERP data for the chosen topic
curl -H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../serp-data/f1a2b3c4-.../
# 3. Generate an authority brief (node_id from step 1)
curl -X POST \
-H "X-API-Key: fyi_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"node_id": "f1a2b3c4-...",
"selected_serp_data": [
{"url": "https://competitor1.com/...", "title": "...", "snippet": "..."},
{"url": "https://competitor2.com/...", "title": "...", "snippet": "..."}
]
}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../briefs/generate/
# 4. Poll until brief is complete (every 10-15 seconds)
curl -H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../briefs/b5c6d7e8-.../status/
# 5. Generate an authority article draft from the completed brief
curl -X POST \
-H "X-API-Key: fyi_live_your_key" \
-H "Content-Type: application/json" \
-d '{"brief_id": "b5c6d7e8-...", "ai_model_id": "claude-sonnet-4", "specialists": {"web_research": true, "fact_check": true}}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../articles/generate/
# 6. Poll until draft is complete (every 15-30 seconds)
curl -H "X-API-Key: fyi_live_your_key" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../articles/c7d8e9f0-.../status/
# 7. Mark the topic as published
curl -X PATCH \
-H "X-API-Key: fyi_live_your_key" \
-H "Content-Type: application/json" \
-d '{"published": true}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../nodes/f1a2b3c4-.../published/

The AI agent can loop through this flow for each topic in the map, prioritizing by importance score and unpublished status.

Zapier: Create a Brand When a Client is Added

Section titled “Zapier: Create a Brand When a Client is Added”

Use a Zapier Webhook step to call the brands endpoint when a new client appears in your CRM:

Terminal window
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"brand_name": "New Client Inc", "website_url": "https://newclient.com"}' \
https://api.floyi.com/api/v1/brands/

Generate an authority brief, create an article, and trigger a draft — the minimum steps to go from a hierarchy topic to content:

Terminal window
# 1. Generate an authority brief (node_id from GET /api/v1/authority/{brand_id}/)
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"node_id": "f1a2b3c4-..."}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../briefs/generate/
# Returns: {"id": "b5c6d7e8-...", "status": "PENDING"}
# 2. Poll until brief is complete (every 10-15 seconds)
curl -H "X-API-Key: fyi_live_your_integration_key" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../briefs/b5c6d7e8-.../status/
# 3. Generate an authority article draft
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"brief_id": "b5c6d7e8-...", "ai_model_id": "claude-sonnet-4"}' \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../articles/generate/
# 4. Poll until draft is complete (every 15-30 seconds)
curl -H "X-API-Key: fyi_live_your_integration_key" \
https://api.floyi.com/api/v1/authority/a1b2c3d4-.../articles/c7d8e9f0-.../status/

For one-off briefs not tied to the authority hierarchy:

Terminal window
# 1. Generate a standalone brief with any topic
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"query_text": "best seo tools for agencies", "brand_id": "a1b2c3d4-..."}' \
https://api.floyi.com/api/v1/briefs/generate/
# 2. Poll until brief is complete
curl -H "X-API-Key: fyi_live_your_integration_key" \
https://api.floyi.com/api/v1/briefs/b5c6d7e8-.../status/
# 3. Generate an article draft from the brief
curl -X POST \
-H "X-API-Key: fyi_live_your_integration_key" \
-H "Content-Type: application/json" \
-d '{"brief_id": "b5c6d7e8-...", "ai_model_id": "claude-sonnet-4"}' \
https://api.floyi.com/api/v1/content/articles/generate/
# 4. Poll until complete
curl -H "X-API-Key: fyi_live_your_integration_key" \
https://api.floyi.com/api/v1/content/articles/c7d8e9f0-.../status/

EndpointMethodScopeDescription
Brands
/api/v1/brands/GETbrands:readList all brands (?search=)
/api/v1/brands/{id}/GETbrands:readGet brand details
/api/v1/brands/POSTbrands:writeCreate a brand
Content Briefs (Standalone)
/api/v1/briefs/GETbriefs:readList standalone briefs (?brand_id= ?status= ?search=)
/api/v1/briefs/{id}/GETbriefs:readGet brief with full data
/api/v1/briefs/{id}/status/GETbriefs:readCheck brief generation status
/api/v1/briefs/generate/POSTbriefs:writeGenerate brief (freeform query_text)
Content Articles (Standalone)
/api/v1/content/articles/GETcontent:readList standalone articles (?brand_id= ?search=)
/api/v1/content/articles/{id}/GETcontent:readGet article details with sections
/api/v1/content/articles/{id}/status/GETcontent:readCheck draft generation progress
/api/v1/content/articles/generate/POSTcontent:writeGenerate article draft from a brief
/api/v1/content/articles/{id}/generate/POSTcontent:writeRegenerate draft for existing article
Topical Maps
/api/v1/maps/GETmaps:readList topical maps (?brand_id=)
/api/v1/maps/{brand_id}/GETmaps:readGet raw map clusters
Topical Research
/api/v1/research/GETresearch:readList research records
/api/v1/research/{brand_id}/GETresearch:readGet full research tree with stats
/api/v1/research/{brand_id}/stats/GETresearch:readGet tree stats only
/api/v1/research/{brand_id}/task-status/GETresearch:readPoll AI generation task status
/api/v1/research/{brand_id}/nodes/rename/PATCHresearch:writeRename a node
/api/v1/research/{brand_id}/nodes/add/POSTresearch:writeAdd a new node
/api/v1/research/{brand_id}/nodes/delete/POSTresearch:writeDelete a node and descendants
/api/v1/research/{brand_id}/nodes/keywords/PATCHresearch:writeAdd/remove keywords on a node
/api/v1/research/{brand_id}/nodes/move/POSTresearch:writeMove node to new parent
/api/v1/research/{brand_id}/nodes/merge/POSTresearch:writeMerge two same-level nodes
/api/v1/research/{brand_id}/nodes/bulk/POSTresearch:writeExecute multiple operations atomically
/api/v1/research/{brand_id}/diff/POSTresearch:readCompare two tree states
Topical Authority
/api/v1/authority/GETauthority:readList authority maps (?brand_id=)
/api/v1/authority/{brand_id}/GETauthority:readGet enriched hierarchy with overrides
/api/v1/authority/{brand_id}/serp-data/{node_id}/GETauthority:readGet stored SERP results for a node
/api/v1/authority/{brand_id}/nodes/{node_id}/published/PATCHauthority:writeToggle published status
Authority Keywords
/api/v1/authority/{brand_id}/nodes/{node_id}/keywords/GETauthority:readList keywords for a node (?source=)
/api/v1/authority/{brand_id}/nodes/{node_id}/keywords/POSTauthority:writeAdd keyword(s) to a node
/api/v1/authority/{brand_id}/nodes/{node_id}/keywords/{keyword_id}/DELETEauthority:writeDelete a keyword
Authority Briefs
/api/v1/authority/{brand_id}/briefs/GETauthority:readList authority briefs (?status= ?search=)
/api/v1/authority/{brand_id}/briefs/{id}/GETauthority:readGet authority brief with full data
/api/v1/authority/{brand_id}/briefs/{id}/status/GETauthority:readCheck authority brief status
/api/v1/authority/{brand_id}/briefs/generate/POSTauthority:writeGenerate brief for a hierarchy node
Authority Articles
/api/v1/authority/{brand_id}/articles/GETauthority:readList authority articles (?search=)
/api/v1/authority/{brand_id}/articles/{id}/GETauthority:readGet authority article with sections
/api/v1/authority/{brand_id}/articles/{id}/status/GETauthority:readCheck draft generation progress
/api/v1/authority/{brand_id}/articles/generate/POSTauthority:writeGenerate article draft from authority brief
/api/v1/authority/{brand_id}/articles/{id}/generate/POSTauthority:writeRegenerate draft for existing authority article
Standalone Clustering
/api/v1/clustering/GETclustering:readList clustering reports
/api/v1/clustering/{id}/GETclustering:readGet report with full cluster results
/api/v1/clustering/{id}/status/GETclustering:readCheck clustering task progress
/api/v1/clustering/{id}/serp-data/?keyword=GETclustering:readGet SERP data for a keyword
/api/v1/clustering/POSTclustering:writeCreate report + start clustering
/api/v1/clustering/{id}/recluster/POSTclustering:writeRe-cluster with new overlap
/api/v1/clustering/{id}/DELETEclustering:writeDelete clustering report
Authority Clustering
/api/v1/authority/{brand_id}/clustering/GETclustering:readGet brand clustering results
/api/v1/authority/{brand_id}/clustering/status/GETclustering:readCheck brand clustering progress
/api/v1/authority/{brand_id}/clustering/serp-data/?keyword=GETclustering:readGet brand SERP data for keyword
/api/v1/authority/{brand_id}/clustering/start/POSTclustering:writeStart brand clustering
/api/v1/authority/{brand_id}/clustering/recluster/POSTclustering:writeRe-cluster brand with new overlap
Images
/api/v1/content/articles/{article_id}/images/GETcontent:readList generated images for an article
/api/v1/content/articles/{article_id}/images/models/GETcontent:readList available image generation models
/api/v1/content/articles/{article_id}/images/analyze/POSTcontent:writeAnalyze content and suggest image placements
/api/v1/content/articles/{article_id}/images/generate/POSTcontent:writeGenerate images for selected placements
/api/v1/content/articles/{article_id}/images/status/?task_id=GETcontent:readCheck image generation task progress
WordPress
/api/v1/cms/wordpress/connections/GETcontent:readList WordPress site connections
/api/v1/cms/wordpress/publish-records/GETcontent:readList publish records (?article_id= ?connection_id=)
/api/v1/cms/wordpress/publish/POSTcontent:writePublish a single article to WordPress
/api/v1/cms/wordpress/bulk-publish/POSTcontent:writeBulk publish up to 50 articles
/api/v1/cms/wordpress/task-status/?task_id=GETcontent:readCheck publish task progress
Content Guide
/api/v1/content-guide/{brand_id}/GETcontent:readGet full content guide (all categories)
/api/v1/content-guide/{brand_id}/summary/GETcontent:readGet entry counts per category
/api/v1/content-guide/{brand_id}/terminology/POSTcontent:writeCreate a terminology entry
/api/v1/content-guide/{brand_id}/compliance/POSTcontent:writeCreate a compliance rule
/api/v1/content-guide/{brand_id}/competitor-policy/POSTcontent:writeCreate a competitor policy
/api/v1/content-guide/{brand_id}/brand-messaging/POSTcontent:writeCreate a brand messaging rule
/api/v1/content-guide/{brand_id}/boilerplate/POSTcontent:writeCreate a boilerplate snippet
/api/v1/content-guide/{brand_id}/ai-generate/POSTcontent:writeStart AI content guide generation
/api/v1/content-guide/{brand_id}/ai-generate/status/?task_id=GETcontent:readCheck AI generation progress
/api/v1/content-guide/{brand_id}/ai-generate/save/POSTcontent:writeSave AI-generated entries to the brand
Authority Organizer
/api/v1/authority/{brand_id}/organizer/overrides/GETauthority:readList active hierarchy overrides
/api/v1/authority/{brand_id}/organizer/move/POSTauthority:writeMove a node to a new parent
/api/v1/authority/{brand_id}/organizer/rename/POSTauthority:writeRename a node
/api/v1/authority/{brand_id}/organizer/combine/POSTauthority:writeCombine two or more nodes into one
/api/v1/authority/{brand_id}/organizer/create/POSTauthority:writeCreate a new node in the hierarchy
/api/v1/authority/{brand_id}/organizer/archive/POSTauthority:writeArchive node(s)
/api/v1/authority/{brand_id}/organizer/restore/POSTauthority:writeRestore archived node(s)
/api/v1/authority/{brand_id}/organizer/clear/POSTauthority:writeClear overrides (reset to baseline)
User
/api/v1/me/profile/GETuser:readGet your profile
/api/v1/me/credits/GETuser:readGet your credit balance
/api/v1/me/teams/GETuser:readList your teams (for X-Team-ID header)
/api/v1/me/audit-logs/GETuser:readPaginated API request logs (?api_key_id= ?method= ?status_code= ?endpoint=)

Only users on the Agency Plan can create API keys.

No. Floyi stores only the SHA-256 hash of the key, not the plaintext. If you lose a key, revoke it and create a new one.

The scopes are set when you create the key based on the key type (Integration or Developer) and any customizations you made. You can also call GET /api/v1/me/ scopes endpoint to see all available scopes and the defaults for each key type.

Existing API keys will stop working immediately. All API requests will return a 401 Unauthorized error until you upgrade back to the Agency plan. Your keys are not deleted — they will resume working once you re-subscribe. You also cannot create new keys while on a non-Agency plan.

The API is designed for server-to-server communication. While technically possible, we recommend against calling the API from client-side JavaScript since it would expose your API key. Use a backend proxy instead.

Not currently. All API requests operate on your live Floyi data. Use a dedicated test brand or workspace to experiment without affecting production content.

How do I find a resource without knowing its ID?

Section titled “How do I find a resource without knowing its ID?”

Use the ?search= query parameter on list endpoints. Search is case-insensitive and supports partial matches:

  • Brands: ?search=floyi searches by brand name
  • Briefs: ?search=topical+authority searches by topic/query text and generated title
  • Articles: ?search=seo+tools searches by article title

You can combine search with other filters: ?search=topical&brand_id=...&status=COMPLETE

All resource IDs are UUIDs (e.g., a1b2c3d4-e5f6-7890-abcd-ef1234567890).

Most list endpoints return all matching results without pagination. Use query filters (e.g., brand_id, status, search) to narrow results. The audit logs endpoint (/api/v1/me/audit-logs/) is paginated with ?page= and ?page_size= parameters.

Yes. API keys are account-level and work with any workspace you have access to. Include the X-Team-ID header with a team UUID to access that team’s data, or omit the header to access your personal workspace. Use GET /api/v1/me/teams/ to discover your team UUIDs. You can only access teams where you are an active member (owner, admin, or member role).

No. Each API key is tied to the user who created it. Only users on the Agency Plan can create keys. If a team member needs API access, they must be on an Agency plan themselves and create their own key. The key inherits the creator’s team memberships — it can only access teams that the key owner belongs to.