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
CLUSTERHub
TOPICBranch
PAGEResource

[!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/
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": "PAGE",
"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, CLUSTER, TOPIC, or PAGE
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] The hierarchy reflects all edits made in Floyi’s Organizer. If you need to build a tree structure, group nodes by mt (pillars), then st2 (clusters), then st3 (topics), then st4 (pages). Use type to identify the level of each node.

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)

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

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 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
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.