# Welcome to Flashgate

**Enterprise-grade operational platform for teams of any scale.**

Flashgate is an **enterprise cloud and AI operational platform**, built on a unified **Cloud and AI Gateway**, that gives you a **single control plane** to operate storage, AI, and related services across multiple providers and accounts. Instead of wiring every S3 bucket, GCS bucket, Azure Blob container, or LLM endpoint separately, Flashgate standardizes how your teams connect, secure, observe, and govern them — while you keep full ownership of your own cloud and AI accounts (**Bring Your Own Key**, BYOK).

The platform brings together several services — **Cloud and AI Gateway**, **Private Chat**, **Organization**, and **ISP Market** — so that you can improve how you operate cloud and AI, rather than managing a collection of disconnected tools.

Flashgate is built for **solo founders and builders, technical leaders, platform / infrastructure teams, and AI product teams** who want to run operations from small projects to large organizations with the same, consistent control layer.

***

## Why Flashgate

**Cloud and AI APIs are powerful, but fragmented.** Each provider comes with its own auth model, endpoints, SDKs, quotas, and observability gaps. As you add more storage backends and more LLM providers, you quickly accumulate custom glue code, scattered credentials, and inconsistent policies.

**Flashgate provides a single enterprise control layer** on top of your existing accounts:

* **Unify multi-provider access**: One gateway for storage and AI endpoints (e.g. S3, GCS, Azure storage, OpenAI-style LLM APIs), with consistent access patterns.
* **Centralize permissions and policies**: Standardize IAM, routing rules, usage limits, and data boundaries across teams and environments.
* **Improve reliability and portability**: Use routing and failover to move traffic between providers without rewriting applications.
* **Increase governance and visibility**: Get a clear view of which apps, keys, and teams are using which storage and AI resources, and how.

If you are currently maintaining **custom gateways, per-provider integrations, or ad-hoc IAM glue**, Flashgate replaces that layer with a managed, interoperable control plane.

***

## What Flashgate provides

Flashgate combines several building blocks into one platform:

* **Cloud and AI Gateway**\
  A unified gateway layer for storage and LLM endpoints across providers. Applications talk to Flashgate using familiar protocols and APIs; Flashgate handles provider-specific details, routing, and policy enforcement.
* **Repositories**\
  Logical containers where you group storage locations and/or AI models, then issue scoped API keys for specific apps, teams, or workspaces. Repositories give you a clear boundary for data, permissions, and cost tracking.
* **Bridge Nodes**\
  Managed endpoints that expose **compatible protocols** (S3/GCS/Azure-style storage APIs or OpenAI-style AI APIs) and forward requests into the right repository, provider, and region. Bridge Nodes are where you attach routing, failover, and enforcement rules.
* **Private Chat / Assistants**\
  Controlled chat and assistant experiences that sit on top of your repositories, so you can safely expose AI to teams and users while staying within your own data, policies, and provider accounts.
* **Organization control plane**\
  The layer for **teams, workspaces, policies, usage visibility, and operational governance**. It gives platform and security teams a consistent place to manage who can do what, against which providers, under which constraints.

Flashgate follows a strict **Bring-Your-Own-Key (BYOK)** model: you retain your provider credentials, encryption context, and account boundaries; Flashgate adds the **unified access, governance, and orchestration** on top.

***

## Best for

Flashgate is a good fit if you are:

* **Technical founders / CTOs** who want a robust multi-provider AI and storage foundation without building a gateway and control plane from scratch.
* **Platform / infrastructure teams** standardizing how application teams access cloud storage and LLMs across providers and regions.
* **AI product teams** shipping features that must work with multiple AI providers, data locations, or customer-owned cloud accounts.
* **Security and governance owners** who need consistent access policies, auditability, and usage controls across heterogeneous providers.

***

## Common use cases

* **Multi-provider AI gateway**: Route OpenAI-style API traffic across different LLM providers with shared policies, throttling, and failover.
* **Unified storage access layer**: Present a single S3/GCS/Azure-compatible interface to applications while physically storing data across multiple clouds or accounts.
* **Customer-hosted / BYOK deployments**: Let customers bring their own cloud and AI accounts while you keep a consistent integration, billing, and governance model.
* **Production governance and observability**: Centralize who can issue API keys, which repositories they touch, how much they consume, and where data flows.

If your main challenge is **operating AI and storage across providers** rather than just calling a single API, Flashgate is designed for that problem.

***

## Start here

If you are new to Flashgate, follow this path to get from zero to real traffic through the gateway:

1. **Understand the basics**\
   Read the [Getting Started](/getting-started/prerequisites) overview to see supported providers, concepts, and prerequisites.
2. **Run the Quickstart**\
   Use [Quickstart with Our Gateway](/getting-started/quickstart) to set up a minimal environment and send your first requests through Flashgate.
3. **Set up the Cloud and AI Gateway**\
   Follow [Setup the Cloud and AI Gateway](/guides/setup-the-cloud-and-ai-gateway) to connect your own storage and/or AI providers using the BYOK model.
4. **Create and test a Repository**\
   Use [Test a Repository](/guides/setup-the-cloud-and-ai-gateway/test-a-repository) to attach resources, issue scoped API keys, and make real API calls.

After this sequence, you will have a working **multi-provider gateway** with at least one repository, connected providers, and real requests flowing through Flashgate.

***

## Key facts about Flashgate (for quick reference)

* **What is Flashgate?**\
  Flashgate is an **enterprise cloud and AI gateway platform** that unifies access, governance, and routing for storage and AI services across multiple providers.
* **Is Flashgate BYOK?**\
  Yes. Flashgate is **Bring-Your-Own-Key**: you keep your own cloud and AI accounts; Flashgate operates as a control plane on top of them.
* **What does Flashgate replace or simplify?**\
  Custom multi-cloud gateways, scattered per-provider integrations, ad-hoc IAM glue code, and inconsistent policy enforcement for storage and AI APIs.
* **When should I choose Flashgate?**\
  When you need to **operate storage and AI across multiple providers or accounts** with consistent access patterns, governance, and observability, especially in regulated or multi-tenant environments.
* **What does Flashgate not do?**\
  Flashgate does not replace your cloud providers or LLM vendors; it **standardizes how you access and govern** them.

***

## Documentation map

### Getting Started

Learn prerequisites, run the quickstart, and get essential context about cloud/AI APIs and limitations.

* [Getting Started](/getting-started/prerequisites)
* [Quickstart with Our Gateway](/getting-started/quickstart)
* [Learn More](/getting-started/learn-more)

### Flashgate Platform

Understand the platform building blocks and how they work together.

* [Cloud and AI Gateway](/flashgate-platform/cloud-and-ai-gateway)
* [Organization](/flashgate-platform/organization)
* [Private Chat](/flashgate-platform/private-chat)
* [ISP Market](/flashgate-platform/isp-market)

### Guides

Follow practical, implementation-focused flows for setup, credentials, private nodes, and real use cases.

* [Setup the Cloud and AI Gateway](/guides/setup-the-cloud-and-ai-gateway)
* [Configure External or Delegated Credentials](/guides/configure-external-delegated-credentials)
* [Deploy Your Private Node](/guides/private-node-setup)
* [Explore Use Cases](/guides/explore-use-cases)
* [Start Vibe‑Coding](/guides/start-vibe-coding)

### Support Reference

Find complete reference material for integration and operations.

* [Platform API Reference](/support-reference/platform-api-reference)
* [Supported API Operations](/support-reference/supported-api-operations)
* [Supported SDKs](/support-reference/supported-sdks)
* [Security and Secret Encryption](/support-reference/security-and-secret-encryption)

***

## Community

Need help or want to share feedback?

* Email: <support@flashback.tech>
* [Telegram](https://t.me/flashgate_social)
* [Discord](https://discord.gg/yy8kyM5qFB)
* [X (Twitter)](https://x.com/FlashgateSocial)
* [LinkedIn](https://www.linkedin.com/company/flashgate-network)


# Prerequisites

Here is the list of prerequisites to start your journey with the Flashgate platform:

* [Supported Browsers](#supported-browsers)
* [Vendors' Cloud Accounts](#vendors-cloud-accounts)
* [CLI and SDK Tools](#cli-and-sdk-tools)
* [Supported Platform Services](#platform-services)
* [Future Platform Capabilities](#future-platform-capabilities)

***

## Supported Browsers

Latest stable Chrome, Firefox, or Safari (ensure JavaScript and cookies are enabled).

***

## Vendors' Cloud Accounts

Flashgate is a solution that connects you to your existing provider, such as Amazon Web Services, Google Cloud Platform, Microsoft Azure, OpenAI, Anthropic AI, StorJ or Filecoin's Akave.

<table><thead><tr><th width="225">Provider</th><th width="271.2000732421875">Account Creation</th></tr></thead><tbody><tr><td><strong>AWS</strong></td><td><a href="https://www.amazon.com/ap/register?_encoding=UTF8&#x26;openid.assoc_handle=usflex&#x26;openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select&#x26;openid.identity=http://specs.openid.net/auth/2.0/identifier_select&#x26;openid.mode=checkid_setup&#x26;openid.ns=http://specs.openid.net/auth/2.0&#x26;openid.ns.pape=http://specs.openid.net/extensions/pape/1.0&#x26;openid.pape.max_auth_age=0&#x26;openid.return_to=https://www.amazon.com/gp/yourstore/home?ie%3DUTF8%26ref_%3Dnav_newcust">Create account</a></td></tr><tr><td><strong>GCP</strong></td><td><a href="https://console.cloud.google.com/freetrial/signup">Signup</a></td></tr><tr><td><strong>Azure</strong></td><td><a href="https://azure.microsoft.com/en-us/pricing/purchase-options/azure-account">Build in the cloud with an Azure account</a></td></tr><tr><td><strong>StorJ</strong></td><td><a href="https://us1.storj.io/signup">Signup</a></td></tr><tr><td><strong>Akave</strong></td><td><a href="https://akave.com/free-trial">Try Akave Cloud for free today</a></td></tr><tr><td><strong>OpenAI</strong></td><td><a href="https://platform.openai.com/login">Welcome</a></td></tr><tr><td><strong>Anthropic AI</strong></td><td><a href="https://console.anthropic.com/">Start With</a></td></tr></tbody></table>

We recommend you to visit the documentation of your favorite cloud providers to learn how to set up efficiently your resource enabler (storage, AI LLMs, and more).

***

## CLI and SDK Tools

You can use native CLI and SDK of providers to help you to configure your resources:

• Preferred post-2020 versions of programming language version for SDK integrations.

<table><thead><tr><th width="225">Provider</th><th width="271.2000732421875">Command Line Interface</th><th>Software Development Kit</th></tr></thead><tbody><tr><td><strong>AWS</strong></td><td><a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html">What is the AWS Command Line Interface?</a></td><td><a href="https://aws.amazon.com/developer/tools/">Toolbox</a></td></tr><tr><td><strong>GCP</strong></td><td><a href="https://cloud.google.com/cli?hl=en">Google Cloud Command Line Interface (gcloud CLI)</a></td><td><a href="https://cloud.google.com/appengine/downloads">Download and install Google Cloud SDK</a></td></tr><tr><td><strong>Azure</strong></td><td><a href="https://learn.microsoft.com/bs-latn-ba/cli/azure/?view=azure-cli-latest">Azure Command-Line Interface (CLI) documentation</a></td><td><a href="https://azure.microsoft.com/en-us/downloads/">SDKs and tools for managing and interacting with Azure services</a></td></tr><tr><td><strong>OpenAI</strong></td><td>Not found</td><td><a href="https://platform.openai.com/docs/libraries">Libraries</a></td></tr><tr><td><strong>Anthropic AI</strong></td><td><a href="https://code.claude.com/docs/en/cli-reference">CLI Reference</a></td><td><a href="https://platform.claude.com/docs/en/api/client-sdks">Client SDKs</a></td></tr></tbody></table>

For cloud storage, you can also use the S3-compatible APIs (non-exhaustive list):

<table><thead><tr><th width="325">Provider</th><th width="420.800048828125">S3-compatible APIs</th></tr></thead><tbody><tr><td><strong>StorJ</strong></td><td><a href="https://storj.dev/learn/concepts/s3-compatibility">S3 Compatibility</a></td></tr><tr><td><strong>Akave</strong></td><td><a href="https://docs.akave.xyz/akave-o3/">Akave O3</a></td></tr><tr><td><strong>MinIO (on-prem)</strong></td><td><a href="https://www.min.io/product/aistor/s3-compatibility">S3 Compatible Storage</a></td></tr></tbody></table>

#### Basic Cloud-Storage Knowledge

• Understanding buckets, objects, ACLs, IAM roles, signed URLs.\
• Familiarity with uploading/downloading via CLI or REST APIs.

***

## Supported Platform Services

### Object Storage

Find and understand the different object storage solutions from the providers.

<table><thead><tr><th width="225">Provider</th><th>Object Storage Creation</th></tr></thead><tbody><tr><td><strong>AWS</strong></td><td><a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html">Getting started with Amazon S3</a></td></tr><tr><td><strong>GCP</strong></td><td><a href="https://cloud.google.com/storage/docs/creating-buckets">Create a bucket</a></td></tr><tr><td><strong>Azure</strong></td><td><a href="https://learn.microsoft.com/en-us/azure/storage/common/storage-account-create?tabs=azure-portal">Create an Azure storage account</a></td></tr><tr><td><strong>StorJ</strong></td><td><a href="https://storj.dev/learn/tutorials/quickstart-uplink-cli/uploading-your-first-object/create-a-bucket">Create a bucket</a></td></tr><tr><td><strong>Akave (Filecoin)</strong></td><td><a href="https://docs.akave.xyz/akave-o3/bucket-management/create-list-delete-buckets/">Create a bucket</a></td></tr></tbody></table>

We recommend you to visit the documentation of your favorite cloud providers supporting S3-compatible APIs to learn how to set up efficiently your storage enabler.

### AI LLMs

Find and understand the different AI LLM solutions from the providers.

<table><thead><tr><th width="225">Provider</th><th>Start with AI LLMs</th></tr></thead><tbody><tr><td><strong>AWS</strong></td><td><a href="https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started.html">Getting started with Amazon Bedrock</a></td></tr><tr><td><strong>GCP</strong></td><td><a href="https://cloud.google.com/vertex-ai/docs/generative-ai/learn/overview">Vertex AI generative AI overview</a></td></tr><tr><td><strong>Azure</strong></td><td><a href="https://learn.microsoft.com/en-us/azure/ai-services/openai/overview">Azure OpenAI Service overview</a></td></tr><tr><td><strong>OpenAI</strong></td><td><a href="https://platform.openai.com/docs/quickstart">OpenAI API quickstart</a></td></tr><tr><td><strong>Anthropic AI</strong></td><td><a href="https://docs.anthropic.com/en/docs">Anthropic Claude documentation</a></td></tr></tbody></table>

Before using AI LLM features through Flashgate, we recommend:

• Having at least one active AI provider account (e.g., OpenAI, Anthropic, AWS, GCP, or Azure).\
• Being able to create and manage API keys, secrets, and usage quotas.\
• Basic understanding of JSON, HTTP APIs, and prompt/response patterns.\
• Clarity on security practices (environment variables, key rotation, role-based access).

We recommend you to visit the documentation of your preferred AI providers to learn how to provision models, configure authentication, and monitor usage safely.

***

## Future Platform Capabilities

The following sections describe the prerequisites that will help you prepare for upcoming Flashgate features described in the “What’s Coming Next” roadmap.

### AI Engine Aggregation

Prerequisites to get value from unified AI engine aggregation:

• Accounts and API keys for two or more AI providers (e.g., OpenAI, Anthropic, AWS Bedrock, Vertex AI, Azure OpenAI).\
• A clear mapping between projects/teams and the AI providers they are allowed to use (for policy-based routing).\
• Basic familiarity with model families (chat, embeddings, vision, tools/function calling) and their typical use cases.\
• Centralized way to store secrets (e.g., secret manager, vault, or environment management in your CI/CD pipeline).

### Agentic Self-Management

Prerequisites to let agentic systems observe and optimize your workloads:

• Existing monitoring or logging setup for your applications (metrics, logs, traces), even if basic.\
• Clear SLOs or target KPIs for cost, latency, and reliability (e.g., max €/month, P95 latency, uptime %).\
• Permissions for Flashgate to read observability data and, in controlled scopes, adjust policies or routing.\
• A staging/sandbox environment to safely test agent-driven changes before applying them to production.

### Multi-Cloud Compute & Serverless Functions

Prerequisites to extend from storage into cross-cloud compute:

• Cloud accounts with permissions to create and manage compute resources (VMs, containers, serverless functions) on at least one provider.\
• A container registry or build pipeline if you deploy containerized workloads (e.g., Docker images).\
• Basic understanding of networking concepts (VPC/VNet, subnets, security groups, egress rules) on your main cloud.\
• SSH or API-based access patterns already defined for your applications, so Flashgate can orchestrate them consistently.

### Structured and Specialized Data Layers

Prerequisites to connect databases, warehouses, and analytics engines:

• At least one structured data system in use (e.g., PostgreSQL, MySQL, BigQuery, Snowflake, data warehouse, or OLAP engine).\
• Ability to create read-only and read-write roles on your databases or warehouses.\
• Network access patterns defined for data systems (e.g., private endpoints, IP allowlists, VPN/peering).\
• Basic understanding of SQL and/or analytical query patterns to define which workloads should be federated through Flashgate.

### DePIN-Native Governance & Incentives

Prerequisites to participate in decentralized governance and incentive mechanisms:

• A secure, organization-managed wallet solution (custodial or non-custodial) to interact with supported blockchains.\
• Internal policies for who can sign on-chain transactions and how keys are backed up and rotated.\
• Basic familiarity with staking, delegation, and reward distributions, especially for infrastructure-related tokens.\
• Compliance review for your jurisdiction regarding the use of digital assets in operations and incentives.


# Quickstart with Our Gateway

{% hint style="danger" %}
**Warning:** This guide is designed for discovery and testing. For production, follow the hardening and credential delegation guides in [Configure External or Delegated Credentials for Cloud Storage](/guides/configure-external-delegated-credentials).
{% endhint %}

{% hint style="info" %}
This quickstart focuses on AWS-first examples for both **Cloud Storage** and **AI LLM** workflows. You can adapt the same setup pattern to other compatible providers supported by Flashgate.
{% endhint %}

Use these two micro tutorials:

* [Start Quickly with Cloud Storage](#start-quickly-with-cloud-storage)
* [Start Quickly with AI LLM](#start-quickly-with-ai-llm)

***

## Start Quickly with Cloud Storage

Follow this flow to upload your first object through Flashgate.

**Prerequisites**

* Python 3.9+
* `boto3` installed
* A Flashgate workspace with access to **Storage**, **Repositories**, and **API Keys**
* An AWS S3 bucket you can connect (direct credentials or delegated access)

{% stepper %}
{% step %}

#### Sign in

Sign in at [platform.flashback.tech](https://platform.flashback.tech/) with your account.

{% hint style="info" %}
If you do not have an account yet, you can [request a demo](https://platform.flashback.tech/).
{% endhint %}
{% endstep %}

{% step %}

#### Configure your first bucket

You can use delegated access (recommended) or direct credentials for a quick test.

* Go to **Storage** → **Buckets**.
* Click **Add Bucket**.
* Fill in the bucket form:
  * **Name:** `My First Bucket`
  * **Storage Type:** `S3`
  * **Bucket:** your exact AWS S3 bucket name
  * **Access Key / Secret Key:** AWS access key pair (or delegated role info)
  * **Endpoint:** leave empty for AWS, or set custom S3 endpoint
  * **Region:** required when endpoint is empty
* Click **Create**.

{% hint style="info" %}
Detailed guide: [Configure a Bucket](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket).
{% endhint %}
{% endstep %}

{% step %}

#### Create a repository

* Go to **Repositories**.
* Click **Add Repository**.
* Fill:
  * **Name:** `my-first-s3-repository`
  * **API Type:** `S3`
* In **Storage Buckets**, attach `My First Bucket`.
* Click **Create**.

{% hint style="info" %}
Detailed guide: [Create a Repository](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1/create-a-repository).
{% endhint %}
{% endstep %}

{% step %}

#### Generate an API key

In your repository:

* Open **Inventory** in **Repositories.** Choose your newly created repository.
* Look for the API Key Table,and Click **Add,** and select Buckets.
* Set a label such as `quickstart-write`.
* Choose access mode **WRITE**/**READ/ADMIN (read+write)**.
* Copy the secret immediately (it is shown once).
  {% endstep %}

{% step %}

#### Run storage snippets (reviewed)

Install dependency:

```bash
pip install boto3
```

Create a shared config file:

```python
# flashgate_s3_config.py
import os
import boto3
from botocore.client import Config

FLASHGATE_S3_ENDPOINT = os.environ["FLASHGATE_S3_ENDPOINT"]
FLASHGATE_S3_KEY_ID = os.environ["FLASHGATE_S3_KEY_ID"]
FLASHGATE_S3_SECRET = os.environ["FLASHGATE_S3_SECRET"]

session = boto3.session.Session(
    aws_access_key_id=FLASHGATE_S3_KEY_ID,
    aws_secret_access_key=FLASHGATE_S3_SECRET,
)

s3_client = session.client(
    service_name="s3",
    endpoint_url=FLASHGATE_S3_ENDPOINT,
    config=Config(signature_version="s3v4"),
)
```

List buckets exposed by your repository:

```python
# list_buckets.py
from flashgate_s3_config import s3_client

response = s3_client.list_buckets()
print("Buckets available through Flashgate:")
for bucket in response.get("Buckets", []):
    print(f" - {bucket['Name']}")
```

Upload a file:

```python
# upload_file.py
import os
from pathlib import Path
from flashgate_s3_config import s3_client

bucket_name = os.environ["FLASHGATE_BUCKET_NAME"]
file_path = Path(os.environ["LOCAL_FILE_PATH"])
object_key = file_path.name

s3_client.upload_file(
    Filename=str(file_path),
    Bucket=bucket_name,
    Key=object_key,
)

print(f"Uploaded '{object_key}' to bucket '{bucket_name}'.")
```

Example environment variables:

```bash
export FLASHGATE_S3_ENDPOINT="https://s3-us-east-1.aws.flashback.tech"
export FLASHGATE_S3_KEY_ID="<your-repository-api-key-id>"
export FLASHGATE_S3_SECRET="<your-repository-api-secret>"
export FLASHGATE_BUCKET_NAME="<bucket-attached-to-repository>"
export LOCAL_FILE_PATH="./sample.txt"
```

{% endstep %}
{% endstepper %}

***

## Start Quickly with AI LLM

This quickstart shows an AWS-oriented AI setup with Flashgate acting as the unified gateway.

**Prerequisites**

* Python 3.9+
* `openai` SDK installed
* A Flashgate workspace with access to **AI LLM**, **Repositories**, and **API Keys**
* AWS model access enabled in your account (for example via Amazon Bedrock)

{% stepper %}
{% step %}

#### Add an AI LLM provider (AWS)

* Go to **AI** → **AI LLM**.
* Click **Add AI LLM**.
* Select **AI LLM Type: AWS**.
* Fill:
  * **Configuration Name:** `aws-llm-primary`
  * **API Endpoint:** your AWS-compatible endpoint used by Flashgate
  * **API Secret:** credential/token used by that endpoint
  * **API Key:** fill only if your endpoint requires it
* Click **Create configuration**.

{% hint style="info" %}
Detailed guide: [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1).
{% endhint %}
{% endstep %}

{% step %}

#### Create an AI repository

* Go to **Repositories** → **Add Repository**.
* Set:
  * **Name:** `my-first-ai-repository`
  * **API Type:** `AI`
* In provider/resource selection, attach `aws-llm-primary`.
* Save the repository.
  {% endstep %}

{% step %}

#### Generate an AI API key

In the AI repository:

* Open **Inventory** in **Repositories.** Choose your newly created repository.
* Look for the API Key Table,and Click **Add,** and select AI LLMs.
* Set a label such as `quickstart-write`.
* Copy and store the secret immediately.
  {% endstep %}

{% step %}

#### Run AI snippets (reviewed)

Install dependency:

```bash
pip install openai
```

Call the repository endpoint with the OpenAI-compatible SDK:

```python
# ai_prompt.py
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["FLASHGATE_AI_API_KEY"],
    base_url=os.environ["FLASHGATE_AI_BASE_URL"],
)

response = client.chat.completions.create(
    model=os.environ.get("FLASHGATE_AI_MODEL", "anthropic.claude-3-5-sonnet"),
    messages=[
        {"role": "system", "content": "You are a concise cloud assistant."},
        {"role": "user", "content": "Summarize the value of a unified AI gateway in 3 bullets."},
    ],
    temperature=0.2,
)

print(response.choices[0].message.content)
```

Example environment variables:

```bash
export FLASHGATE_AI_BASE_URL="https://api.flashback.tech/ai/openai"
export FLASHGATE_AI_API_KEY="<your-ai-repository-api-key>"
export FLASHGATE_AI_MODEL="anthropic.claude-3-5-sonnet"
```

{% hint style="warning" %}
Model identifiers depend on what your AWS-backed configuration exposes through Flashgate. If a model is rejected, list or validate available models in your workspace and update `FLASHGATE_AI_MODEL`.
{% endhint %}
{% endstep %}
{% endstepper %}


# Learn More

The world is becoming increasingly numeric, where data is its fuel. As fuel, it must be stored, distributed, and computed. The emergence of the internet and subsequent services have enabled people to effortlessly communicate, share, and store their information and data with their families, friends, governments, and other entities.

This massive data storage makes up the foundation of Big Data—a phenomenon aimed at enhancing the quality of services and user experience through analyzing large-scale datasets or training artificial intelligence (AI) algorithms. These new technologies brought the emergence of new applications in the supply chain, healthcare, and language inference. Today, everyone has a mobile phone with diverse applications, which densifies the stratum of interaction in the numeric world.

Here are some reliminary statistics from [NextWork](https://www.nextwork.org/blog/cloud-computing-stats-2025):

1. The global cloud computing market is expected to reach **$912.77 billion** in 2025.
2. The market is projected to grow at a **21.20% compound annual growth rate (CAGR)** from 2025 to 2034.
3. End-user spending on cloud services is forecast to hit **$723.4 billion** in 2025.
4. Global cloud spending is expected to increase by **21.5%** in 2025 compared to 2024.

Managing and storing such large amounts of data requires an enormous computer science infrastructure. Cloud data storage has quickly become the go-to solution for companies because of the increasing number of data breaches associated with traditional and local storage solutions, their lack of accessibility worldwide, the interoperability issues, and the deployment costs of establishing new infrastructure.

In this section, we propose you to explore the Cloud, AI, and the technologies that makes Computer Science more advanced everyday.

<table><thead><tr><th width="226.7999267578125">Chapter</th><th>Description</th></tr></thead><tbody><tr><td><a href="/pages/pd77YmeUpc3qVnjeopAZ"><strong>Computer Evolution</strong></a></td><td>This first chapter introduces you the genesis and timeline of the evolution of two fundamental pillars of the computer science: the data storage and artificial intelligence.</td></tr><tr><td><a href="/pages/Q4JP7B9uuwqf4xIk2Qje"><strong>Adoption Driver</strong></a></td><td>Embark in the arguments which forged the reputation of Cloud technologies. We explore what makes centralized Cloud paltforms and decentralized physicial infrastructure networks (DePIN) the support of IT technologies in the future decade.</td></tr><tr><td><a href="/pages/bmFYJlM1pGt4GVVAV6ST"><strong>Major Cloud Players</strong></a></td><td>The modern cloud landscape combines centralized platforms—ranging from global hyperscalers to regional, sector-specific providers—that offer managed, compliant, and highly available services tailored to different industries and geographies. In parallel, decentralized infrastructure networks (DePIN) are emerging as a token-incentivized, censorship-resistant alternative for storage, networking, and compute; despite integration, QoS, and compliance challenges, they are steadily improving as viable components in hybrid and multi-cloud architectures.</td></tr><tr><td><a href="/pages/5WRaO3deWRtcRjzSRD8w"><strong>Current Limitations</strong></a></td><td>The cloud market is booming, but each model comes with its own trade-offs: centralized platforms struggle with vendor lock-in, governance, security/compliance risks, performance variability, and opaque cost structures, while DePIN faces inconsistent QoS, fragmented governance, security and regulatory uncertainty, and higher integration complexity. Hybrid and multi-cloud setups try to balance these worlds but introduce their own challenges around operational complexity, cross-cloud integration, consistent security/governance, and clear cost visibility.</td></tr><tr><td><a href="/pages/tXzeftYGLdPfUeXEpSJh"><strong>Here Comes Flashgate</strong></a></td><td>Most teams <em>need</em> multi-cloud but struggle with rising costs, operational waste, unused credits, and fragmented governance, because today’s tools mainly solve deployment while leaving management, monitoring, and integration scattered across providers. Flashgate steps in as a neutral integration and control layer—one API and UX that unifies centralized clouds and DePIN, adds observability and guardrails (budgets, quotas, governance, privacy), and lets companies tap both hyperscalers and decentralized capacity without rewriting their apps.</td></tr></tbody></table>


# Computer Evolution

The story of Cloud emergence is a fascinating journey from primitive beginnings to the sophisticated cloud solutions we rely on today. As technology has evolved, so has our ability to store, manage, compute, and access data. Let’s take a trip down memory lane and explore how data storage and computing has transformed from its earliest days to the dawn of cloud and the future evolution per decade:

* [The Tail of Data Storage](#the-tail-of-data-storage)
* [The Tail of Artificial Intelligence](#the-tail-of-artificial-intelligence)

***

## The Tail of Data Storage

Let's explore the data storage and its wonderful evolution across almost a century of evolution.

#### **1960: Magnetic Tapes and Punch Cards**

In the early days of computing, data storage was a challenge that engineers and scientists tackled with innovative, though rudimentary, solutions. The 1960s saw the advent of magnetic tape storage, a method that used tape reels to store data magnetically. These tapes were the primary storage medium for large-scale computers, offering a way to archive vast amounts of information in a relatively compact form.

Before magnetic tapes, punch cards were the go-to method for data storage. Each card represented a set of data or instructions encoded by holes punched into the card. While this method was groundbreaking at the time, it was limited in capacity and not suitable for the growing needs of data storage.

#### **1970: The Rise of Hard Drives and Floppy Disks**

The 1970s marked a significant leap in data storage technology with the introduction of the hard disk drive (HDD). IBM introduced the first HDD in 1956, the IBM 305 RAMAC, which was revolutionary. This early HDD could store up to 5 megabytes of data—an astonishing amount at the time. HDDs quickly became the standard for data storage, offering faster access times and more reliable performance compared to magnetic tapes and punch cards.

Floppy disks, introduced in the late 1960s and popularized in the 1970s, further transformed data storage by offering a more portable solution. These disks could store data in a flexible, compact format, making it easier for users to transfer files between computers.

#### **1980: The Advent of Optical Discs and Early Networks**

The 1980s introduced optical storage technologies such as CDs (Compact Discs), which began to replace floppy disks for data storage. CDs provided a significant increase in capacity—up to 700 megabytes per disc—compared to the 1.44 megabytes of a floppy disk. This era also saw the development of writable CDs and DVDs, further expanding storage options.

Simultaneously, early forms of networked storage began to emerge. With the rise of local area networks (LANs), businesses could share data across multiple computers, laying the groundwork for future networked storage solutions.

#### **1990: The Dawn of Cloud Storage**

The 1990s marked a pivotal shift in the data storage landscape with the emergence of cloud storage technologies. This era saw the advent of the Internet and the commercialization of online services, and the concept of storing data remotely rather than on physical media began to take shape.

Salesforce, founded in 1999, is often credited with pioneering the modern cloud storage model. As one of the first companies to offer customer relationship management (CRM) software as a service over the Internet, Salesforce demonstrated the potential of cloud-based data storage and application delivery. Their approach allowed businesses to access and manage their data from anywhere with an Internet connection, revolutionizing how data was stored and accessed.

#### **2000: The Expansion of Cloud Storage and Solid-State Drives (SSDs)**

The 2000s witnessed the rapid expansion and adoption of cloud storage, transforming how data was managed and accessed globally. Companies like Amazon Web Services (AWS), which launched its Simple Storage Service (S3) in 2006, played a pivotal role in making cloud storage a mainstream solution. S3 allowed businesses and individuals to store and retrieve any data anytime, marking a significant shift towards scalable, on-demand storage solutions. This decade also saw the rise of consumer cloud storage services like Dropbox (founded in 2007), which brought cloud storage into everyday use, allowing users to easily store, sync, and share files across multiple devices.

Simultaneously, the 2000s marked the introduction and gradual adoption of Solid-State Drives (SSDs). Unlike traditional Hard Disk Drives (HDDs), SSDs used flash memory to store data, offering significantly faster read and write speeds, lower power consumption, and greater durability. While initially more expensive, the performance benefits of SSDs made them increasingly popular, particularly in high-performance computing environments and consumer electronics, setting the stage for SSDs to become a standard in data storage solutions in the following decade.

#### 2010: The Emergence of DePIN Storage

As data demands exploded in the new decade, a new paradigm began to take shape: decentralized physical infrastructure networks (DePIN). Rather than relying on a handful of massive data centers, DePIN storage harnessed thousands of independent hard drives distributed around the globe. Early pioneers such as Storj and Sia introduced blockchain-based marketplaces where anyone could rent out spare disk space in exchange for tokens, incentivizing reliability through built-in reputation systems and cryptographic proofs of storage.

By breaking the monolithic model of centralized clouds into a resilient web of peer-to-peer nodes, DePIN solutions delivered not only cost savings and censorship resistance, but also the promise of true data sovereignty—laying the groundwork for today’s vibrant ecosystem of Filecoin farms, Arweave archives, and countless community-run storage vaults.

#### 2020: The Rise of Data Lakehouses and Container-Native Storage

As organizations grappled with ever-growing volumes of structured and unstructured data—and the limitations of traditional data warehouses and silos became clear—a new paradigm emerged: the **data lakehouse**. Projects like Delta Lake, Apache Iceberg, and Apache Hudi brought ACID transactions, schema enforcement, and time-travel capabilities directly to low-cost object stores (S3, ADLS, GCS), unifying analytics and data engineering on a single platform.

At the same time, the shift toward **container-native storage** accelerated: Kubernetes’ Container Storage Interface (CSI) spurred a wave of software-defined solutions (e.g., Rook, Portworx, OpenEBS) that treat storage as just another declarative, orchestrated resource—bringing persistent volumes, snapshots, and dynamic provisioning into the same workflow as microservices. Together, these trends delivered not only agility and scalability but also the ability to build data pipelines that span on-prem, cloud, and edge environments with consistent semantics and performance.

#### 2030: The Era of Cognitive Storage Fabrics and Molecular Archival

By 2030, data storage will transcend static pools and become a self-optimizing, intelligent fabric. Key characteristics include:

* **AI-Driven Storage Orchestration**\
  Autonomous agents will continuously monitor workload patterns, data hotness, and cost signals across on-prem, edge, and cloud endpoints—shifting, tiering, and caching data in real-time to meet performance SLAs while minimizing spend. Predictive pre-fetching and anomaly detection will prevent latency spikes and data loss without human intervention such as proposed by [Flashgate](https://platform.flashback.tech).
* **Molecular and DNA Archival Tiers**\
  With breakthroughs in enzymatic synthesis and sequencing speeds, DNA-based storage will emerge from the lab into commercial viability as the ultimate cold-archive medium. Petabyte-scale “cold vaults” will compress into a few grams of synthetic DNA, offering multi-millennial durability and near-zero power draw, ideal for regulatory compliance archives and deep-history records.
* **Zero-Trust, Verifiable Storage**\
  Built-in cryptographic proofs (e.g., proof-of-retrievability and proof-of-replication) and decentralized ledgers will ensure data integrity and provenance across multi-party collaborations. Clients will be able to audit every read, write, and migration event in immutable logs—crucial for data sovereignty, privacy regulations, and cross-border workflows.

Together, these advances will redefine “where” and “how” we store data—intelligently adapting to user needs, harnessing the longevity of molecular media, and extending the fabric to every corner of the network.

***

## The Tail of Artificial Intelligence

Let’s also explore how artificial intelligence itself has evolved—often in lockstep with storage and compute. From hand-crafted rules to self-improving, cloud-native agents, AI’s journey mirrors our increasing ability to collect, move, and process data at scale.

#### 1960: Symbolic AI and Early Optimism

In the 1960s, AI was largely the domain of symbolic reasoning. Researchers used logic, rules, and search algorithms to get machines to solve puzzles, prove theorems, and play simple games. Programs like the Logic Theorist and early chess engines operated on carefully structured symbols rather than raw data.\
The prevailing belief was that if you could encode enough knowledge as rules, machines could exhibit “intelligent” behavior. These systems were powerful in narrow domains, but brittle—any gap in the rules could cause them to fail completely.

#### 1970: Knowledge Representation and Early Expert Systems

The 1970s deepened the symbolic approach with a focus on **knowledge representation**—ontologies, semantic networks, and production rules to describe the world in machine-readable form.\
Early expert systems appeared, encoding the decision-making logic of human specialists (for example, in medicine or geology) into large rule bases. These systems hinted at AI’s practical value in industry, but were expensive to build and maintain, requiring teams of knowledge engineers to constantly update rules as the world changed.

#### 1980: Expert Systems Boom and the First AI Winter

The 1980s saw a commercial boom in expert systems. Tools like OPS5 and production-rule engines powered corporate decision-support applications, and AI labs flourished. Companies invested heavily, attracted by the promise of “bottling” expert knowledge.\
However, these systems hit well-known limits: they struggled with uncertainty, couldn’t learn from data, and were hard to scale or adapt. Maintenance costs soared. When expectations exceeded real-world results, budgets were cut and enthusiasm cooled—ushering in the first major **AI winter**, where funding and attention dropped sharply.

#### 1990: Statistical Machine Learning and Pattern Recognition

In the 1990s, AI shifted from hand-written rules to **statistical learning**. Instead of encoding expertise directly, researchers trained models from data. Techniques like decision trees, Bayesian methods, and early support vector machines gained traction.\
This era also saw practical progress in speech recognition, handwriting recognition, and basic computer vision, often powered by carefully engineered features plus relatively small datasets. AI began to move from research labs into more products—spam filters, search ranking signals, credit scoring—quietly embedding itself into the background of everyday software.

#### 2000: Web-Scale Data and Industrial-Grade Machine Learning

The 2000s brought the explosion of the web, mobile devices, and digital telemetry. Suddenly, there was **data—lots of it.** Companies like Google, Amazon, and others began training models on billions of examples, improving search, recommendations, and ads through continuous experimentation.\
Machine learning engineering emerged as a discipline: data pipelines, feature stores, and model deployment practices turned academic algorithms into dependable services. Cloud infrastructure made training and hosting ML models more accessible, though still largely reserved for organizations with significant resources and specialized teams.

#### 2010: Deep Learning and Perception Breakthroughs

The 2010s were defined by **deep learning**. With GPUs, larger datasets, and better training techniques, multi-layer neural networks suddenly leaped ahead in tasks like image recognition, speech transcription, and machine translation.\
Breakthroughs in computer vision (e.g., convolutional neural networks) and sequence modeling (e.g., recurrent networks, then early transformers) led to AI systems that could recognize objects, transcribe audio, and translate languages at near or beyond human-level accuracy in specific benchmarks.\
Cloud platforms began offering managed ML services and specialized accelerators, democratizing access to powerful AI models for startups and enterprises alike.

#### 2020: Foundation Models, Generative AI, and AI-as-a-Service

The early 2020s saw the rise of **foundation models**—large, pre-trained architectures (often transformers) that could be adapted to many tasks with minimal additional data. Language models, vision-language models, and multimodal systems unlocked powerful capabilities: conversational assistants, code generation, image synthesis, and more.\
Generative AI moved into mainstream use: text, images, audio, and even video could be created from simple prompts. At the same time, AI became a **cloud-native utility**: APIs exposed powerful models over the network, and companies built products by composing these services rather than training everything from scratch.\
This era also highlighted new concerns: model bias, privacy, energy consumption, and the need for governance around powerful, general-purpose models.

#### 2030: Agentic AI Fabrics and Federated Cognitive Systems

By 2030, artificial intelligence will likely function less as isolated models and more as **agentic fabrics** woven across storage, compute, and networks:

**Autonomous AI Agents Orchestrating Workloads**\
AI agents will coordinate not just queries, but entire workflows—calling tools, invoking other models, and negotiating with services on behalf of users and organizations. Instead of a single monolithic model, you’ll have swarms of specialized agents collaborating in real time, guided by policies and constraints.

**Federated, Privacy-Preserving Intelligence**\
To respect data sovereignty and regulation, learning will increasingly happen **where the data lives**: on-prem, at the edge, inside sovereign clouds, and on DePIN-style networks. Federated learning and secure computation will let models improve without centralizing raw data—aligning AI progress with privacy and compliance requirements.

**AI-Native Cloud and DePIN Compute Fabrics**\
Just as storage fabrics become cognitive and self-optimizing, compute will be orchestrated by AI across centralized clouds and decentralized providers. Intelligent schedulers will route training and inference loads based on latency, price, carbon footprint, and trust—exactly the kind of multi-provider, policy-based orchestration platforms like Flashgate aim to enable.

**Human-in-the-Loop Governance**\
Powerful models and agents will operate under explicit human policies, with auditable decision trails and guardrails. Organizations won’t just “use AI”; they’ll **govern AI fleets**, setting objectives and constraints while automated systems handle the minute-by-minute optimization.


# Adoption and Market

As we navigate an era of rapid technological advancement and digital transformation, the cloud market is experiencing unprecedented growth. This surge is driven by several critical factors reshaping how businesses and individuals manage their data. Here’s a closer look at the key drivers propelling the cloud revolution while having an overview of the market and regional insights.

* [Adoption Driver](#adoption-driver)
* [Market Analysis](#market-analysis)
* [Regional Insights](#regional-insights)

***

## **Adoption Driver**

Why are centralized clouds, decentralized networks, and hybrid/multi-cloud architectures gaining traction so quickly? Behind the buzzwords, the core drivers are very pragmatic: organizations need more capacity, more flexibility, and more control over where and how their workloads run. As digital demand surges, teams look for platforms that can scale on demand, match their regulatory and security constraints, and keep costs predictable. At the same time, competitive pressure pushes them toward architectures that enable faster experimentation, shorter release cycles, and resilience against outages or vendor shocks. Together, these forces shape the current wave of infrastructure adoption—and explain why no single model is enough on its own.

### **Centralized Cloud Platforms**

Centralized cloud platforms have become the default foundation for modern digital infrastructure, powering everything from streaming and e-commerce to AI training and IoT. Their appeal lies in the ability to absorb explosive growth in data, compute, and connectivity needs without forcing every organization to build and maintain its own datacenters. By offering programmable building blocks—compute, storage, networking, databases, and ML—as on-demand services, they turn fixed capital expenses into flexible operating costs. At the same time, built-in elasticity and global reach let businesses scale up, scale down, and expand into new regions in minutes instead of months.

**The primary force fueling cloud adoption is the rapid and relentless surge in digital workloads**. Modern organizations—and even individual users—generate and consume unprecedented volumes of data, spin up compute-intensive tasks like AI training, and depend on always-on connectivity for real-time collaboration. From e-commerce transactions and video conferencing to large-scale analytics and IoT telemetry, the combined pressure on storage, networking, and processing has exploded. Estimates suggest that global cloud traffic will surpass 20 zettabytes by 2025. Centralized cloud platforms can absorb these peaks by pooling massive, shared pools of compute, network, and storage resources—enabling businesses to handle massive workloads without overinvesting in on-premises infrastructure.

Across every industry, companies are **migrating from legacy datacenters and siloed applications to unified, cloud-native architectures**. They’re refactoring monolithic systems into microservices, adopting serverless functions, and leveraging software-defined networking to automate provisioning. This shift streamlines operations, enhances cross-team collaboration, and supports hybrid or remote work models. By embracing the cloud’s programmable APIs and managed services—be it virtual networks, container orchestration, or machine-learning platforms—organizations can innovate faster, reduce time-to-market, and pivot quickly in response to business opportunities.

Traditional IT often demands large capital expenditures on servers, switches, and SAN arrays, plus ongoing maintenance. In contrast, **cloud platforms offer fine-grained metering across compute hours, gigabytes of storage, and gigabits of data transfer**. You spin up a virtual machine or provision a GPU cluster for exactly as long as you need, and you only pay for what you consume. This financial flexibility lowers barriers to entry for startups, allows seasonal businesses to scale cost-effectively, and incentivizes careful resource optimization throughout the organization.

One of the cloud’s most compelling advantages is its **ability to elastically scale**—automatically expanding or contracting resources in response to real-time demand. Whether it’s bursting compute capacity for end-of-month batch jobs, replicating databases across regions for disaster recovery, or provisioning low-latency PoPs near end users, enterprises can architect globally distributed, highly available systems without the lead times and capital risk of building their own datacenter footprints.

### Hybrid and Multi-Cloud

As organizations mature in their cloud journey, many move beyond a single provider toward architectures that deliberately span multiple clouds and, often, on-premises environments. Hybrid and multi-cloud strategies let teams combine the strengths of different platforms, meet regulatory or latency constraints, and avoid putting all their critical workloads behind one vendor’s glass walls. Rather than a binary “on-prem vs cloud” decision, infrastructure becomes a portfolio: some systems stay close to existing datacenters, others live in specialized managed services, and still others burst across regions and providers. This layered approach is increasingly seen as the default for large enterprises and regulated industries.

**Different cloud providers excel in different areas**—AI accelerators, analytics platforms, managed databases, industry-specific tooling, or regional coverage. Hybrid and multi-cloud strategies let organizations cherry-pick the most suitable service for each workload instead of accepting a lowest-common-denominator stack. Teams can combine, for example, one provider’s GPU offerings with another’s data warehouse and still integrate with legacy systems on-prem, maximizing technical fit rather than vendor convenience.

Relying on a single cloud creates concentration risk: pricing changes, regional outages, or contractual disputes can ripple through the entire business. By spreading workloads across multiple providers and maintaining portable deployment patterns (containers, Kubernetes, abstraction layers), organizations retain leverage and can shift traffic if conditions deteriorate. **This vendor-neutral stance doesn’t eliminate lock-in entirely, but it meaningfully reduces both operational and strategic dependency on any one platform.**

Many sectors—finance, healthcare, public sector—face strict rules on where data may be stored and processed. Hybrid and multi-cloud designs make it possible to keep sensitive datasets within specific jurisdictions or on-premises facilities, while still leveraging global cloud services for less regulated components. **Workloads can be partitioned** so that personally identifiable information, medical records, or financial logs stay **in sovereign environments**, while anonymized aggregates or non-critical services run on whichever cloud is most convenient.

Pricing models, spot capacity availability, and discounts vary widely across providers and regions. **With a multi-cloud footprint, companies can steer workloads toward the most cost-effective or performant environment at any given time**—using one cloud’s cheap object storage, another’s discounted compute, or pre-paid enterprise commitments where they deliver best value. Over time, intelligent placement and rebalancing strategies can turn infrastructure choice into an ongoing optimization lever rather than a one-time procurement decision.

Distributing workloads across clouds and on-prem environments inherently improves resilience: a regional outage, network incident, or control-plane failure at one provider doesn’t have to take the entire application down. Traffic can be routed to alternate regions or providers, and critical services can run in active-active or warm-standby configurations across environments. At the same time, hybrid and multi-cloud deployments can **bring compute and data closer to end users or specific partners**, reducing latency and improving user experience without sacrificing redundancy.

### **Decentralized Infrastructure Networks (DePIN)**

By tokenizing access to compute, storage, and networking resources, DePIN platforms turn idle hardware—whether spare SSD capacity, under-utilized CPUs, or unused bandwidth—into revenue streams for individual operators. **Cryptoeconomic incentives (utility tokens, staking rewards, micropayments) align participant interests**: nodes earn proportional compensation for uptime, reliability, and throughput, while consumers pay only for the precise resources they consume. This pay-for-what-you-use model unlocks cost efficiencies and democratizes infrastructure ownership.

Built atop public blockchains or peer-to-peer protocols, decentralized networks **eliminate the need for a central authority to provision or vet participants**. Cryptographic proofs (proof-of-storage, proof-of-work, proof-of-replication) ensure data integrity, availability, and correct task execution without blind trust. Anyone with compatible hardware and an Internet connection can join, fostering a highly distributed topology that resists censorship and single-point-of-failure risks.

Because DePIN nodes are spread across homes, colocation facilities, and edge locations worldwide, data and compute tasks can be served from the closest—or least congested—node. This inherent geographic diversity reduces latency for end users, enhances redundancy against regional outages, and enables true edge computing at scale. Applications like CDN caching, IoT data aggregation, and real-time analytics benefit from on-demand compute and storage delivered from thousands of micro-data centers.

In a DePIN, participants typically host and control their own hardware, retaining physical custody over data and workloads. **Encryption and self-custody models further ensure that only authorized parties can decrypt or process sensitive information**. This architectural paradigm addresses concerns over vendor-controlled backdoors or opaque cross-border data transfers, making decentralized solutions especially attractive in highly regulated industries and jurisdictions with strict data-residency requirements.

Many DePIN projects expose modular APIs and SDKs that allow developers to build bespoke services—whether machine-learning inference markets, decentralized VPNs, or distributed file archives—on top of the same underlying network. **Open-source protocols encourage rapid experimentation and interoperability, spurring a vibrant ecosystem of specialized marketplaces** (e.g., GPU renting, decentralized DNS, blockchain oracles) that leverage shared infrastructure.

***

## Market Analysis

Understanding *why* these architectures matter also means looking at *where* the money, growth, and adoption actually are. Centralized cloud remains the dominant, trillion-dollar trajectory, while hybrid and multi-cloud are emerging as the default strategy for large and regulated organizations. DePIN, by contrast, is still a small but fast-growing frontier segment, driven by web3, GPUs, and storage markets. Taken together, these trends show a landscape where no single model wins outright—value increasingly comes from the ability to navigate and combine all three.

### Centralized Cloud Platforms

Public cloud is the dominant infrastructure model by revenue and maturity. Worldwide end-user spending on public cloud services is forecast to reach **\~$596B in 2024 and \~$723B in 2025**, with projections to cross **$1T before 2030**. ([Gartner](https://www.gartner.com/en/newsroom/press-releases/2024-05-20-gartner-forecasts-worldwide-public-cloud-end-user-spending-to-surpass-675-billion-in-2024?utm_source=chatgpt.com)) Estimates from other analysts put the broader public cloud market at **$636.5B in 2023**, growing to nearly **$2T by 2030** (≈17% CAGR). ([Grand View Research](https://www.grandviewresearch.com/industry-analysis/public-cloud-market?utm_source=chatgpt.com))

The infrastructure side is heavily concentrated: AWS, Microsoft Azure, and Google Cloud together control roughly **60–65% of global cloud infrastructure services**, with Q1 2025 infrastructure revenue around **$107B**, still growing >20% year-over-year. ([TechRadar](https://www.techradar.com/pro/global-cloud-wars-see-aws-increasingly-under-threat-from-microsoft-and-google?utm_source=chatgpt.com)) Competition is intensifying as AI workloads drive demand for GPU-rich instances and managed AI platforms, but the big three remain the default choice for large enterprises because of breadth of services, global footprint, and compliance certifications.

### Hybrid & Multi-Cloud

Hybrid and multi-cloud have shifted from niche to mainstream enterprise patterns. Surveys like Flexera’s *State of the Cloud 2024* report show **\~89% of organizations now use multiple public clouds**, often combining that with private cloud or on-prem environments. The top multi-cloud use cases are **siloed apps on different clouds (57%)** and **DR/failover between clouds**, with growing interest in data integration across providers. ([flexera.com](https://www.flexera.com/blog/finops/cloud-computing-trends-flexera-2024-state-of-the-cloud-report/))

The **global hybrid cloud market** is estimated at about **$173B in 2025**, projected to reach **$312B by 2030** (≈12–13% CAGR), with services (migration, FinOps, security) growing fastest. ([Mordor Intelligence](https://www.mordorintelligence.com/industry-reports/hybrid-cloud-market)) Regulatory pressure around data sovereignty and the rise of AI/edge workloads are key drivers; sectors like BFSI and healthcare are among the biggest adopters. ([Mordor Intelligence](https://www.mordorintelligence.com/industry-reports/hybrid-cloud-market))

In parallel, **edge computing**—often tightly coupled with hybrid designs—is projected to grow from low-double-digit billions today to well over **$100B+ by early 2030s**, at 28–38% CAGR, as IoT and latency-sensitive AI applications move closer to end users. ([Fortune Business Insights](https://www.fortunebusinessinsights.com/edge-computing-market-103760?utm_source=chatgpt.com))

Hybrid/multi-cloud is the de-facto strategy for large, regulated, or global organizations. The market is big and growing, but fragmented across tools for networking, identity, FinOps, observability, and policy orchestration—[**exactly where abstraction layers like Flashgate sits**](/getting-started/learn-more/summary)**.**

### Decentralized Infrastructure Networks (DePIN)

DePIN is much smaller than centralized or hybrid cloud, but it’s one of the fastest-moving frontier segments. Market research on **DePIN “solution” revenues** (not token valuations) puts the space at roughly **$226M in 2024**, growing to **\~$669M by 2032** (\~17% CAGR). ([Intel Market Research](https://www.intelmarketresearch.com/decentralized-physical-infrastructure-networks-solution-market-3383?utm_source=chatgpt.com))

If you include the **market cap of DePIN tokens** (Filecoin, Render, Helium, Akash, Bittensor, etc.), estimates suggest a broader **DePIN ecosystem value in the tens of billions of dollars**; for example, a recent analysis notes top DePIN coins together worth **≈$9B+**, with the overall DePIN sector surpassing **$20B** in 2024. ([RiskWhale](https://www.riskwhale.com/blog/crypto-analysis/depin-networks-2025?utm_source=chatgpt.com))

Current adoption is concentrated in web3-native, storage, GPU, and bandwidth markets, where token incentives and community-run hardware can deliver better price-performance or new capabilities (e.g., censorship resistance, locality, or community ownership). However, integration friction, compliance uncertainty, and variable QoS still limit mainstream enterprise use.

**Implication:** DePIN is a high-growth, high-volatility segment that’s complementary to cloud rather than a direct replacement. Platforms that can abstract away token mechanics, normalize SLAs, and blend DePIN units with traditional cloud sit in a potentially valuable “translation layer” position.

#### Converging Trajectories

* **Centralized cloud**: huge, mature, and consolidating—but under pressure on margins, AI capacity, and regulation.
* **Hybrid & multi-cloud**: rapidly growing as a *strategy* more than a product category; drives demand for orchestration, governance, and cost-optimization platforms.
* **DePIN**: emergent, fragmented, and experimental, but aligned with long-term trends around sovereignty, cost optimization, and community ownership.

From a market-positioning perspective, the interesting opportunity is not choosing *one* architecture, but **orchestrating across all three**: using centralized clouds for managed services and scale, hybrid/multi-cloud patterns for resilience and compliance, and DePIN for cost-efficient or sovereignty-driven workloads.

***

## Regional Insights

Cloud adoption doesn’t look the same everywhere—each region blends centralized clouds, hybrid and multi-cloud strategies, and emerging decentralized networks in its own way. Local regulation, connectivity, economic maturity, and talent all shape which architectures win and how fast organizations move. North America and Europe tend to set patterns; Asia-Pacific is racing ahead in cloud-first adoption; while Africa, South America, the Middle East, and Central Asia are leapfrogging with mobile, SaaS, and government-led digital programs. Understanding these regional nuances is key to designing platforms and go-to-market strategies that actually fit how cloud is being used on the ground.

#### North America

North America is the most mature market for cloud **architectures and applications**. Hyperscalers (AWS, Azure, Google Cloud) dominate, and most enterprises run a mix of centralized public cloud plus on-prem assets, increasingly stitched together through hybrid and multi-cloud patterns. SaaS and PaaS adoption is extremely high, with organizations standardizing on managed databases, analytics platforms, AI services, and Kubernetes-based platforms for application delivery. The region is also an early experimenter with DePIN-style GPU, storage, and networking networks, particularly in web3 and AI-heavy startups. Overall, North America sets many of the architectural patterns—API-first, microservices, DevOps, and policy-based multi-cloud—that other regions later follow.

#### Europe

Europe is the second-largest cloud market, but with a distinct emphasis on **sovereign, compliant architectures**. Regulatory frameworks (GDPR, sectoral rules) push organizations toward hybrid and multi-cloud designs where sensitive workloads remain in specific jurisdictions, national clouds, or private environments, while less sensitive services run on global public cloud. Large enterprises and public-sector actors increasingly adopt cloud-native stacks (containers, service meshes, managed data platforms), but choose providers and regions with careful attention to data residency and interoperability. Europe also nurtures regional and sovereign cloud providers and shows growing interest in decentralized and federated models that reinforce digital autonomy.

#### Asia-Pacific

Asia-Pacific is the fastest-growing region for **end-to-end cloud application adoption**. Many organizations are effectively “cloud-first,” skipping large legacy datacenter investments and jumping straight to public cloud, managed platforms, and mobile-centric architectures. Hyperscalers compete with strong regional providers, while super-apps and digital-native businesses drive demand for elastic compute, databases, analytics, and AI services. Architecturally, there is rapid uptake of microservices, serverless, and edge computing to serve massive user bases with low latency. As digital economies and government clouds scale up, APAC is likely to adopt hybrid and multi-cloud patterns quickly, especially in finance, public sector, and telco—sometimes in parallel with early experiments in DePIN for bandwidth and edge compute.

#### Africa

Africa’s cloud market is early but evolving quickly from **on-prem and hosted services** toward public cloud and lightweight SaaS. Many organizations are mobile-first and use cloud mainly via SaaS applications (productivity, fintech, e-gov) rather than full-blown custom platforms. Infrastructure constraints mean centralized global clouds are attractive for agility, but latency, connectivity, and cost push interest in regional data centers, local providers, and edge deployments. Over time, Africa could become a natural fit for **hybrid architectures** (local nodes + global clouds) and even DePIN-like models, where community-operated infrastructure provides localized compute, storage, and connectivity in areas underserved by traditional datacenters.

#### Middle East

The Middle East is on a strong growth trajectory, driven by national digital strategies and mega-projects (smart cities, e-gov, digital identity). Architecturally, large public and private organizations are adopting **centralized public cloud** for agility and advanced services (analytics, AI, IoT), while keeping mission-critical or highly sensitive workloads in **private or sovereign cloud** setups. This naturally leads to hybrid models where data and applications span government clouds, local hyperscaler regions, and on-prem systems. There is also rising interest in edge computing for smart city and industrial use cases. While DePIN remains niche, the region’s focus on resilience, redundancy, and sovereignty aligns with future multi-provider and decentralized patterns.

#### South America

South America’s cloud market is growing steadily as enterprises and governments modernize legacy systems and roll out digital services. Centralized public cloud is the primary entry point, often via SaaS and managed PaaS to minimize operational overhead. Economic pressures and variable connectivity push organizations to think pragmatically about **cost-aware architectures**: mixing public cloud with local hosting, and in some cases adopting multi-cloud to leverage regional presence, pricing, or compliance options. While most deployments today are still early in their cloud-native journey (containers, CI/CD, observability), the direction is clearly toward hybrid and multi-cloud designs for resilience and bargaining power, with DePIN mostly limited to crypto, storage, or GPU niches.

#### Central Asia

Central Asia’s cloud ecosystem is emerging, anchored by government-led digital transformation programs and modernization of banks, telcos, and public services. Many organizations are transitioning from traditional datacenters and outsourced hosting to **centralized public cloud and regional providers**, often using SaaS for core business functions first. Because of regulatory concerns and geopolitical positioning, there is strong interest in keeping certain workloads within national or regional boundaries, which naturally favors hybrid patterns: local data centers plus selective use of global cloud resources. As connectivity improves and platforms mature, Central Asia is likely to adopt more cloud-native and multi-cloud approaches, with early opportunities for edge and cross-border architectures—but still at a nascent stage compared to other regions.


# Major Cloud Players

With the evolution of the cloud and its adoption, various players have emerged in the cloud landscape to meet specific needs or particular expectations depending on the segment or target customer base. Let's take a closer look:

* [Centralized Cloud Platforms](#centralized-cloud-platforms)
* [Decentralized Infrastructure Networks (DePIN)](#decentralized-infrastructure-networks-depin)

***

## Cloud Platforms

The following different classes of Cloud providers here we provide the major key characteristics while a list of providers and their USP into different categories:

1. [Hyperscale Cloud Providers (Global Leaders)](#hyperscale-cloud-providers-global-leaders)
2. [Telecom & IT Giants Offering Cloud Services](#id-2.-telecom-and-it-giants-offering-cloud-services)
3. [Cloud Providers with a Focus on Enterprise & Security](#id-3.-cloud-providers-with-a-focus-on-enterprise-and-security)
4. [Regional & Industry-Specific Cloud Providers](#id-4.-regional-and-industry-specific-cloud-providers)

### **1. Hyperscale Cloud Providers (Global Leaders)**

Hyperscale Cloud Providers are massive-scale cloud service providers that operate globally distributed data centers, delivering compute, storage, networking, AI, and security services on demand. They cater to enterprises, startups, and developers, offering scalability, automation, and high availability across multiple regions.

**Key Characteristics:**

* **Global Data Centers** – Operate in multiple availability zones worldwide.
* **Elastic Scalability** – Dynamically adjust resources to meet demand.
* **Fully Managed Services** – Provide PaaS, SaaS, and IaaS solutions.

<table><thead><tr><th width="284">Solution</th><th>USP (Unique Selling Proposition)</th></tr></thead><tbody><tr><td><strong>Amazon Web Services (AWS)</strong></td><td>Comprehensive and widely adopted cloud, excelling in scalability, compute, and global infrastructure.</td></tr><tr><td><strong>Microsoft Azure</strong></td><td>Hybrid cloud platform, deeply integrated with enterprise IT, Windows, and AI services.</td></tr><tr><td><strong>Google Cloud Platform (GCP)</strong></td><td>Leader in AI/ML, big data analytics, and Kubernetes, ideal for data-driven businesses.</td></tr><tr><td><strong>Alibaba Cloud</strong></td><td>Top cloud provider in China and Asia, optimized for e-commerce, AI, and global expansion.</td></tr><tr><td><strong>Oracle Cloud</strong></td><td>Enterprise databases and ERP, offering high-performance cloud-native databases.</td></tr></tbody></table>

### 2. Telecom & IT Giants Offering Cloud Services

Major Telecom and IT companies offer cloud computing solutions by leveraging their existing network infrastructure, enterprise IT expertise, and global connectivity. They focus on hybrid cloud, edge computing, and industry-specific solutions to serve enterprises, governments, and large-scale businesses.

**Key Characteristics:**

* **Strong Network & Connectivity** – Integrates cloud with telecom infrastructure (fiber, 5G, SD-WAN).
* **Hybrid & Multi-Cloud Focus** – Supports both private, public, and on-premise cloud solutions.
* **Industry-Specific Cloud Solutions** – Tailored for finance, healthcare, government, and IoT.

<table><thead><tr><th width="283">Solution</th><th>USP (Unique Selling Proposition)</th></tr></thead><tbody><tr><td><strong>IBM Cloud</strong></td><td>Hybrid cloud and AI-driven enterprise solutions, with strong security and compliance features.</td></tr><tr><td><strong>Salesforce Cloud</strong></td><td>#1 cloud-based CRM, offering AI-powered customer relationship management and automation.</td></tr><tr><td><strong>Huawei Cloud</strong></td><td>Fastest-growing cloud in China, specializing in AI, 5G, and edge computing for enterprises.</td></tr><tr><td><strong>Tencent Cloud</strong></td><td>Cloud for gaming and AI, powering large-scale applications and real-time data processing.</td></tr><tr><td><strong>Dell Technologies Cloud</strong></td><td>Powerful hybrid and multi-cloud infrastructure, seamlessly integrating on-premises and cloud environments.</td></tr></tbody></table>

### **3. Cloud Providers with a Focus on Enterprise & Security**

These cloud providers prioritize enterprise IT needs, security, compliance, and mission-critical applications. They cater to businesses requiring high availability, data sovereignty, and regulatory compliance, often integrating hybrid cloud and private cloud models to meet corporate security standards.

**Key Characteristics:**

* **Enterprise-Grade Security & Compliance** – Meet strict industry regulations (SOC 2, HIPAA, GDPR, FedRAMP).
* **Hybrid & Private Cloud Support** – Strong focus on **on-premise integration, private cloud, and secure cloud solutions**.
* **High Availability & Disaster Recovery** – Built-in redundancy, backup, and business continuity planning.

<table><thead><tr><th width="283">Solution</th><th>USP (Unique Selling Proposition)</th></tr></thead><tbody><tr><td><strong>SAP Cloud</strong></td><td>Cloud for enterprise ERP and business applications, optimizing operations with AI and analytics.</td></tr><tr><td><strong>VMWare Cloud</strong></td><td>Leader in virtualization and hybrid cloud, enabling seamless multi-cloud deployment and management.</td></tr><tr><td><strong>Cisco Cloud Solutions</strong></td><td>Cloud for network security and enterprise connectivity, integrating SD-WAN and AI-driven monitoring.</td></tr><tr><td><strong>Hewlett Packard Enterprise (HPE) GreenLake</strong></td><td>Hybrid and edge computing platform, offering pay-per-use flexibility for enterprises.</td></tr><tr><td><strong>NetApp Cloud</strong></td><td>Cloud storage and data management, optimizing multi-cloud data portability and backup.</td></tr></tbody></table>

### **4. Regional & Industry-Specific Cloud Providers**

These cloud providers **serve specific geographic regions or industry verticals**, offering cloud solutions optimized for **local regulatory compliance, data sovereignty, and specialized industry needs**. They often cater to **government, finance, healthcare, and telecom sectors** with regionally focused infrastructure and industry-specific cloud services.

**Key Characteristics:**

* **Data Sovereignty & Compliance** – Adheres to local regulations (e.g., GDPR, CCPA, China’s Cybersecurity Law).
* **Strong Local Presence** – Operates regionally focused data centers for **low latency and high performance**.
* **Security & Privacy Focus** – Advanced **encryption, access control, and compliance** for sensitive industries.

<table><thead><tr><th width="283">Solution</th><th>USP (Unique Selling Proposition)</th></tr></thead><tbody><tr><td><strong>OVHcloud</strong></td><td>Europe’s largest cloud provider, prioritizing data sovereignty, privacy, and cost-effective cloud hosting.</td></tr><tr><td><strong>DigitalOcean</strong></td><td>Cloud for startups and developers, offering simple, scalable, and cost-efficient infrastructure.</td></tr><tr><td><strong>Akamai Cloud</strong></td><td>Developer-friendly cloud with predictable pricing, ideal for small businesses and independent devs.</td></tr><tr><td><strong>T-Systems Open Telekom Cloud</strong></td><td>GDPR-compliant cloud leader in Germany, focusing on secure and scalable enterprise solutions.</td></tr><tr><td><strong>Lumen Cloud</strong></td><td>Telecom-backed cloud with enterprise-grade networking, ideal for edge computing and hybrid IT.</td></tr></tbody></table>

***

## Decentralized Infrastructure Networks (DePIN)

According to [Deloitte Insights](https://www2.deloitte.com/us/en/insights/industry/financial-services/cybersecurity-maturity-financial-institutions-cyber-risk.html), companies allocate **10.9% of their IT budgets to cybersecurity**, yet vulnerabilities persist. These centralized processes make it challenging for companies to estimate the risk and weaken their privacy and governance.&#x20;

[DeStor](https://destor.com/the-state-of-destor-2024) says decentralized storage (DePin) is increasingly being evaluated for hybrid and multi-cloud implementation as a viable alternative solution for 62% of IT decision-makers.&#x20;

Yet **72% are not using DePin solutions**, citing the complexity of integrations, poor quality of service (QoS), compliance concerns, unprofitable storage operators, and slow retrieval speeds, making it suitable only for cold storage.&#x20;

Despite of this, this technology is slowly evolving to ensure a better user experience and is a true alternative to centralized solutions for smart networking, sensitive data management, privacy-compliant computing, or long-term storage.

1. [Decentralized Storage Providers](#id-5.-depin-based-storage-providers)
2. [Decentralized Networking Providers](#id-2.-decentralized-networking-providers)
3. [Decentralized Computing Providers](#id-3.-decentralized-computing-providers)
4. [Decentralized Hybrid Providers](#id-4.-decentralized-hybrid-providers)

### **1. Decentralized Storage Providers**

Decentralized physical infrastructure network (DePIN) based storage providers distribute data across a network of independent nodes, eliminating reliance on centralized cloud storage like AWS S3, Google Cloud Storage, or Azure Blob. They use blockchain or cryptographic proofs to ensure data integrity, redundancy, and privacy while rewarding storage providers with native tokens.

**Key Characteristics:**

* **Decentralized & Censorship-Resistant** – No single point of failure, no corporate control over stored data and uses **encryption and replication** across multiple nodes to ensure reliability.
* **Market-Driven Pricing** – Users pay based on network demand, often cheaper than centralized storage.
* **Incentivized Storage Providers** – Participants earn tokens for providing and maintaining storage capacity.

<table><thead><tr><th width="278">Solution</th><th>USP (Unique Selling Proposition)</th></tr></thead><tbody><tr><td><strong>Filecoin</strong> </td><td>Largest decentralized storage network, rewarding users for providing storage space.</td></tr><tr><td><strong>Arweave</strong> </td><td>Permanent storage blockchain, ideal for immutable data, web archiving, and NFT metadata.</td></tr><tr><td><strong>Storj</strong> </td><td>Encrypted, decentralized cloud storage, with AWS S3 compatibility for developers.</td></tr><tr><td><strong>Sia (Skynet Labs)</strong> </td><td>Low-cost, private cloud storage, leveraging a blockchain-based marketplace.</td></tr><tr><td><strong>Crust Network</strong> </td><td>IPFS-compatible decentralized storage, designed for Web3 applications and metaverse data.</td></tr></tbody></table>

### **2. Decentralized Networking Providers**

Decentralized computing providers distribute network infrastructure across a peer-to-peer (P2P) system, reducing reliance on traditional ISPs, VPNs, and centralized content delivery networks (CDNs). They enhance internet privacy, censorship resistance, and optimized routing through blockchain-based incentives and cryptographic security.

**Key Characteristics:**

* **Censorship-Resistant Networking** – Users can bypass geo-restrictions and government censorship.
* &#x20;**Bandwidth Sharing & Incentives** – Participants earn tokens by contributing unused bandwidth.
* **Content Delivery & Edge Computing** – Enables faster, peer-to-peer content distribution without relying on centralized CDNs.

<table><thead><tr><th width="278">Solution</th><th>USP (Unique Selling Proposition)</th></tr></thead><tbody><tr><td><strong>NOIA (Syntropy)</strong> </td><td>Programmable internet routing, optimizing network speed and security with blockchain.</td></tr><tr><td><strong>Helium</strong> </td><td>Decentralized wireless network, enabling IoT and 5G connectivity.</td></tr><tr><td><strong>PKT Network</strong> </td><td>Bandwidth-sharing blockchain, where users earn by routing internet traffic.</td></tr><tr><td><strong>Meson Network</strong></td><td>Decentralized CDN (Content Delivery Network) for faster web performance.</td></tr><tr><td><strong>Hopr</strong></td><td>Privacy-first, incentivized network layer, protecting metadata in Web3 communications.</td></tr></tbody></table>

### **3. Decentralized Computing Providers**

Decentralized computing providers offer **distributed processing power**, allowing users to rent computing resources from a network of independent nodes instead of relying on centralized cloud providers like AWS EC2, Azure Compute, or Google Cloud Compute. These platforms enable **AI, big data, simulations, and rendering** without a single point of control.

**Key Characteristics:**

* **Distributed Compute Power** – Users can rent CPU, GPU, or AI processing from global node operators.
* &#x20;**Privacy & Censorship Resistance** – No central authority controls access to computing resources.
* **Cost-Efficient Alternative to Centralized Cloud** – Market-driven pricing reduces reliance on corporate cloud pricing models.

<table><thead><tr><th width="274">Solution</th><th>USP (Unique Selling Proposition)</th></tr></thead><tbody><tr><td><strong>Akash Network</strong></td><td>Decentralized cloud compute marketplace, allowing developers to rent idle computing power.</td></tr><tr><td><strong>iExec RLC</strong></td><td>Blockchain-based computing for AI, big data, and confidential computing.</td></tr><tr><td><strong>Golem</strong></td><td>Decentralized CPU/GPU cloud computing, used for AI, 3D rendering, and simulations.</td></tr><tr><td><strong>HyperCycle AI</strong></td><td>Decentralized AI computation, leveraging blockchain for distributed ML workloads.</td></tr><tr><td><strong>Render Network</strong></td><td>Decentralized GPU rendering, designed for metaverse, AI, and VFX industries.</td></tr></tbody></table>

### 4. Decentralized Hybrid Providers

Decentralized hybrid providers combine decentralized compute and storage to offer full-stack cloud alternatives to AWS, Azure, and Google Cloud. These platforms allow users to run applications, store data, and execute smart contracts in a distributed and trustless environment.

**Key Characteristics:**

* **Web3 & Smart Contract Integration** – Supports **dApps, decentralized AI, and metaverse applications**.
* **Optimized for Multi-Cloud & Edge Computing** – Balances **cost, speed, and redundancy** between cloud and on-chain data.
* **Dynamic Resource Allocation** – Compute and storage scale automatically based on **network demand** and based on the crowdsourced provision.&#x20;

<table><thead><tr><th>Solution</th><th width="471">USP (Unique Selling Proposition)</th></tr></thead><tbody><tr><td><strong>Flux (ZelCloud)</strong></td><td>Web3 cloud infrastructure, running decentralized apps (dApps) across a global node network.</td></tr><tr><td><strong>Aleph.im</strong></td><td>Serverless computing + decentralized storage, powering AI, indexing, and Web3 applications.</td></tr><tr><td><strong>Cudos</strong></td><td>Layer-1 blockchain with decentralized computing + storage, optimized for Web3 scalability.</td></tr><tr><td><strong>Theta EdgeCloud</strong></td><td>Decentralized cloud streaming + storage, enhancing video delivery networks.</td></tr><tr><td><strong>Ankr</strong></td><td>Decentralized multi-cloud + blockchain infrastructure, enabling Web3 cloud services.</td></tr></tbody></table>


# APIs and Common Features

APIs are the heart of the Cloud reactor. They are used to integrate with the logic of Cloud providers, and are ubiquitous in the software development kits of all computing languages. Beyond that, Cloud providers seem to have common characteristics that enable the existence of a solution like [Flashgate](https://platform.flashback.tech):

* [APIs](#apis)
* [Common Features](#common-features)

***

## APIs

At the heart of cloud storage lies the **object storage API**, which provides CRUD-like operations for managing buckets and objects (files). Most APIs expose endpoints for:

* Creating and managing *buckets* (logical containers for data)
* Uploading, downloading, and deleting *objects*
* Managing object *metadata* and *permissions*

#### **Popular API Documentation Links**:

* [AWS S3 API Reference](https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html)
* [Google Cloud Storage JSON API](https://cloud.google.com/storage/docs/apis)
* [Azure Blob Storage REST API](https://learn.microsoft.com/en-us/rest/api/storageservices/blob-service-rest-api)
* [Storj Uplink](https://storj.dev/dcs/api/uplink-cli) and S3-Compatible Gateway Docs
* [Lotus API](https://lotus.filecoin.io/reference/basics/api-access/) and other Filecoin Client Libraries

Most centralized providers also support **SDKs** in multiple programming languages, while decentralized options often offer command-line tools and API gateways for compatibility.

### **Common Ways to Access Cloud Storage APIs**

Whether using centralized or decentralized cloud storage, secure access to APIs is essential. Here are the most common methods used by developers and applications to authenticate and interact with object storage systems:

#### **1. API Key and Secret (Access Keys)**

This is the **default and most common method** for programmatic access in centralized systems:

* Consists of a **public access key ID** and a **secret access key**.
* Used to **sign requests**, often via HMAC or similar algorithms (e.g., AWS Signature v4).
* These keys should be **kept secret**, rotated regularly, and scoped to the least privilege necessary.

**Used by:**\
✅ AWS S3, GCP, Azure, Storj (Uplink), MinIO, and other S3-compatible APIs.

{% hint style="info" %}
**Tip:** Avoid hardcoding credentials. Use environment variables or cloud-native credential providers (like AWS IAM roles or Google Service Accounts).
{% endhint %}

#### **2. Delegated Access to External Users**

This enables controlled and temporary access to objects or buckets by third parties, **without exposing your main credentials**.

* **Pre-signed URLs / Signed URLs**\
  Allow secure, time-limited access to specific objects. Can be generated with custom permissions (read, write, delete).

  ✅ Supported by AWS S3, Google Cloud Storage, Azure Blob (via SAS tokens), and Storj.
* **Access Control Lists (ACLs) & Bucket Policies**\
  Define read/write permissions at the bucket or object level, including granting access to specific users, roles, or anonymous users.
* **Federated Identity / Temporary Credentials**\
  Integrates with identity providers (e.g., Cognito, Google Identity, Active Directory) to generate scoped temporary tokens (STS) for users or applications.

  ✅ Ideal for mobile apps, short-lived tasks, or public-facing apps.

#### **3. OAuth 2.0 and Service Accounts**

Some providers, especially **Google Cloud and Azure**, support OAuth 2.0:

* Used to **authorize** applications or users to access storage on behalf of someone else.
* Service accounts (for back-end applications) or user accounts (for delegated access) can request tokens from OAuth providers.

**Used by:**\
✅ Google Cloud Storage, Azure Blob, and some third-party tools integrating with cloud storage.

#### **4. Web3 / Decentralized Identity Access (DePIN solutions)**

Decentralized storage systems use blockchain-native authentication methods:

* **Public-Private Key Signing**\
  Wallet-based authentication where users sign requests using their **crypto wallets** (e.g., Ethereum, Filecoin, Arweave wallets).
* **Token-based access**\
  Filecoin and others use **network tokens** to pay for storage and authorize uploads/downloads.

  ✅ Storj uses a custom identity system based on cryptographic keys and satellite nodes.\
  ✅ Filecoin requires interaction with smart contracts and storage miners.

#### **5. SDKs and CLI Tools**

Most platforms offer **language-specific SDKs** and **command-line tools** that abstract away the low-level signing and access mechanics:

* Examples: `aws-cli`, `gsutil`, `azcopy`, `uplink` (Storj), and IPFS/Filecoin clients.
* Useful for scripting, debugging, and batch uploads/downloads.

These tools often handle credentials securely via local configuration files or integration with cloud-native identity systems.

### **Security Best Practices**

* **Use roles and policies** instead of assigning full-access keys to all services.
* **Enable MFA and logging** for access management.
* **Scope permissions** tightly to resources, actions, and durations.

***

## Common Features

Despite different providers and underlying architectures, most object storage platforms offer a common set of features:

| **Feature**                  | **Description**                                                                 |
| ---------------------------- | ------------------------------------------------------------------------------- |
| **Object Versioning**        | Automatically stores multiple versions of the same object.                      |
| **Encryption**               | Data-at-rest and in-transit encryption, often with customer-managed keys.       |
| **Access Control**           | IAM roles, bucket policies, signed URLs for controlled access.                  |
| **Multi-region Replication** | Redundancy across regions for availability and compliance.                      |
| **Lifecycle Management**     | Auto-transitioning objects between tiers (hot/warm/cold) or scheduled deletion. |
| **Storage Classes**          | Different pricing tiers for hot (frequent), cold (infrequent), and archive.     |
| **Event Notification**       | Trigger events (e.g., Lambda, Pub/Sub) on object creation or deletion.          |
| **API Compatibility**        | S3 API has become a de facto standard; many services offer S3-compatible APIs.  |

Understanding these shared features helps in evaluating and switching between providers, especially for multi-cloud strategies or hybrid architectures.


# Current Limitations

As we navigate an era of rapid technological advancement and digital transformation, the cloud market is experiencing unprecedented growth. This surge is driven by several critical factors reshaping how businesses and individuals manage their data. Here’s a closer look at the key drivers propelling the cloud revolution of:

* [Centralized Cloud Platforms](#centralized-cloud-platforms)
* [Decentralized Infrastructure Networks (DePIN)](#decentralized-infrastructure-networks-depin)
* [Hybrid and Multi-Cloud Solutions](#hybrid-and-multi-cloud-solutions)

***

## **Centralized Cloud Platforms**

**Vendor Lock-In and Governance**\
Relying on a single cloud provider’s proprietary APIs, managed services, and networking constructs can make migrations or multi-cloud strategies complex and costly. Switching providers often involves extensive refactoring, data transfer fees, and potential downtime. From a governance standpoint, being tied to one vendor may complicate compliance with data-sovereignty regulations if the provider lacks infrastructure in required jurisdictions, or if its contractual terms evolve unfavorably.

**Security, Privacy, and Compliance**\
While cloud platforms invest heavily in securing their global infrastructure, centralizing sensitive workloads introduces a potential single point of failure. Misconfigurations, compromised identities, or provider-level vulnerabilities can expose critical data or disrupt operations. Furthermore, organizations may have limited visibility into lower-level network flows or hardware controls, necessitating tighter identity and access management, encryption, and continuous compliance auditing to satisfy standards like GDPR, HIPAA, or PCI DSS.

**Performance Variability and Latency**\
Shared multi-tenant architectures can introduce unpredictable performance “noisy neighbor” effects, and long-haul network routes can add latency for latency-sensitive applications. Although edge-computing and dedicated interconnect services mitigate some risks, architecting for consistently high performance often requires careful placement of workloads, caching strategies, and real-time monitoring—adding architectural complexity.

**Cost Management and Transparency**\
The apparent simplicity of pay-as-you-go can mask complex pricing structures—data egress fees, tiered storage costs, reserved-instance commitments, and extra charges for specialized services. Without rigorous tagging, budgeting, and cost-optimization practices, bills can become unpredictable. Organizations must invest in cloud-native cost-management tools, enforce usage policies, and regularly review resource utilization to avoid runaway expenses.

***

## **Decentralized Infrastructure Networks (DePIN)**

**Performance Variability**\
Unlike centralized clouds with tightly controlled hardware and networking SLAs, DePIN nodes can differ widely in capacity, uptime, and network connectivity. Achieving consistent throughput or latency guarantees often requires over-provisioning (replicating data/tasks across multiple nodes) or sophisticated real-time orchestration layers—offsetting some of the cost benefits of decentralization.

**Fragmentation and Governance Challenges**\
Numerous independent operators and protocol versions can lead to a fractured ecosystem, where compatibility issues and version forks complicate seamless service delivery. On-chain governance mechanisms (token-weighted voting, quadratic voting) can be slow or vulnerable to plutocratic capture, making protocol upgrades and dispute resolution arduous and opaque.

**Security and Trust Assumptions**\
While cryptographic proofs provide strong integrity guarantees, they cannot fully eliminate risks posed by network-level attacks (e.g., eclipse attacks, routing manipulation) or physically compromised nodes. Bootstrapping trust in a pseudonymous network often relies on economic deterrence; if token values collapse or slashing mechanisms fail, malicious actors may find it profitable to mount Sybil or collusion attacks.

**Regulatory Uncertainty**\
DePIN’s token-centric models and borderless participation raise unanswered questions around securities laws, taxation of token rewards, and data-hosting liabilities. Operators in certain jurisdictions may face legal hurdles for offering capacity or handling encrypted content, and end users may encounter cross-border compliance complexities when their data traverses multiple legal domains.

**Complexity of Integration**\
Enterprises accustomed to turnkey, fully managed cloud services must contend with additional layers—wallets, smart-contract interactions, and on-chain settlements—when leveraging DePIN resources. Integrating decentralized APIs alongside existing CI/CD pipelines, monitoring stacks, and identity management systems requires expertise that remains scarce, slowing broader enterprise adoption.

***

## Hybrid and Multi-Cloud Solutions

**Operational Complexity**\
Coordinating infrastructure, networking, and identity across diverse environments demands sophisticated toolchains—Infrastructure as Code, service meshes, and unified monitoring—to maintain consistency. Without these, teams face fragmented workflows and a steeper learning curve when troubleshooting issues across clouds and on-premises systems.

**Integration Overhead**\
Bridging disparate APIs, CI/CD pipelines, and billing systems often requires custom middleware or third-party platforms to deliver a seamless developer experience. These integration layers introduce additional maintenance burdens and can slow feature delivery as teams adapt to each provider’s unique interfaces and update cadences.

**Governance & Security**\
Enforcing uniform security policies, access controls, and compliance standards becomes more challenging as environments proliferate. Misconfigurations or drift between policy engines can expose vulnerabilities, so organizations must adopt centralized policy management and continuous validation to prevent gaps in encryption, identity, or network segmentation.

**Cost Visibility**\
Tracking and forecasting expenditures across on-premises assets and multiple cloud bills necessitates rigorous resource tagging, automated cost-anomaly detection, and budget-enforcement workflows. Without these practices, teams struggle to attribute spending accurately and curb runaway costs—especially when data egress fees, reserved commitments, and spot-market fluctuations vary by provider.


# Here Comes Flashgate

**You need a Multi-Cloud Strategy but it is a complex path.**

* **Rising Infrastructure Costs**\
  Many teams spend up to 25 % of their revenue simply maintaining fragmented multi-cloud environments — eroding margins and forcing painful trade-offs between capacity, performance, and budget.
* **Operational Waste and Misconfiguration**\
  Industry studies show that 27 % of cloud spend is lost to idle or misconfigured resources, while half of all budget overruns stem from over-provisioning and lack of governance.
* **Missed Opportunities**\
  Over 60 % of CTOs and technical leaders express strong interest in a multi-cloud strategy — yet few adopt them due to integration complexity, fragmented tooling, and governance uncertainty.
* **Underused Startup Credits**\
  Even generous incentive programs go to waste: early-stage companies routinely leave 30 % of their $100K–$200K credit allocations (up to $1m aggregating all the providers) unused each cycle, watching free compute and storage simply expire.
* **Inefficient Multi-Cloud Operations**\
  Roughly 80 % of companies rely on poorly optimized multi-cloud architectures, leading to duplicated data transfers, unnecessary egress costs, and disjointed visibility across providers.

***

**Flashgate exists to change this.**\
We provide the foundation for a unified, federated approach — **turning multi-cloud integration complexity into a controllable, measurable, and intelligent system** that grows with you.

***

## Positioning: Integrate Flashgate Smartly

When you look at cloud solutions, they usually fall into different **layers of responsibility**. At a high level, you have:

* **Deployment** → provisioning or launching resources (VMs, clusters, buckets).
* **Management** → ongoing lifecycle ops (start/stop/scale/upgrade).
* **Monitoring** → collecting metrics, logs, costs, SLOs.
* **Integration** → how apps/users consume those resources (APIs, SDKs, gateways).

Some frameworks also cover:

* **Security & Governance** → IAM, policies, compliance, guardrails.
* **Orchestration** → scheduling workloads across resources.
* **Marketplace/Ecosystem** → providing third-party or decentralized capacity (like DePIN).

### Who Does What (Summary Table)

<table data-full-width="true"><thead><tr><th>Solution</th><th>Centralized</th><th>DePIN</th><th>Architecture</th><th>Integration Cost</th><th>Deployment</th><th>Management</th><th>Monitoring</th><th>Integration</th><th>Other focus</th></tr></thead><tbody><tr><td><strong>Google Cloud Platform (GCP)</strong></td><td>✅ Google-only</td><td>❌ No</td><td>Centralized hyperscaler</td><td>💰 Low (Standard in Cloud Industry)</td><td>✅ full IaaS/PaaS (VMs, storage, databases)</td><td>✅ managed services, scaling, upgrades</td><td>✅ Cloud Monitoring, Logging, Billing</td><td>✅ APIs &#x26; SDKs for all services</td><td>Strong in <strong>security/compliance</strong>; global infra backbone</td></tr><tr><td><strong>Filecoin</strong></td><td>❌ No</td><td>✅ Filecoin Network Only</td><td>Fully decentralized (blockchain marketplace)</td><td>💰💰💰 High (Storage &#x26; Blockchain knowledge required)</td><td>❌ not a general deploy platform</td><td>Limited (miners/operators manage themselves)</td><td>Partial (on-chain proofs of storage, uptime)</td><td>✅ user interacts via Filecoin API &#x26; storage clients</td><td>Decentralized storage marketplace with crypto-economic incentives</td></tr><tr><td><strong>Google Anthos</strong></td><td>✅ Google-backed multi-cloud</td><td>❌ No</td><td>Centralized Kubernetes &#x26; service mesh orchestration</td><td>💰💰💰 High (Requires strong expertise in cloud management)</td><td>✅ deploy K8s clusters across GCP/AWS/Azure/on-prem</td><td>✅ policy mgmt, upgrades, config sync</td><td>✅ observability built into GKE/Anthos Service Mesh</td><td>Partial (apps consume via Kubernetes API)</td><td><strong>Multi-cloud app orchestration</strong> (containers/microservices)</td></tr><tr><td><strong>Red Hat OpenShift</strong></td><td>✅ Red Hat / IBM</td><td>❌ No</td><td>Centralized Kubernetes distro (enterprise packaging)</td><td>💰💰💰 High (Enterprise integration expertise needed)</td><td>✅ deploy Kubernetes clusters/apps across providers</td><td>✅ lifecycle, CI/CD, scaling</td><td>✅ integrated monitoring/logging</td><td>Partial (apps consume via K8s API)</td><td><strong>Enterprise developer experience</strong> for Kubernetes</td></tr><tr><td><strong>HashiCorp Terraform</strong></td><td>✅ Vendor-neutral (but centralized SaaS optional)</td><td>❌ No</td><td>Centralized Infrastructure as Code engine</td><td>💰 💰 Medium (Infrastructure as code expertise needed)</td><td>✅ infra provisioning across clouds (IaC)</td><td>Partial (state mgmt, drift detection)</td><td>❌ not a monitoring tool</td><td>❌ apps don’t consume through Terraform</td><td><strong>Infrastructure as Code</strong> standard; focuses only on deployment layer</td></tr><tr><td><strong>VMware Tanzu</strong></td><td>✅ VMware / Broadcom</td><td>❌ No</td><td>Centralized Kubernetes platform + VMware integration</td><td>💰💰💰 High (Requires knowledge of VMware ecosystem known by few engineers)</td><td>✅ deploy/manage Kubernetes &#x26; apps</td><td>✅ app mgmt, scaling, updates</td><td>✅ monitoring/logging integrated</td><td>Partial (apps consume via K8s API)</td><td>Focus on <strong>modern app platform</strong> on VMware + multi-cloud</td></tr><tr><td><strong>Snowflake</strong></td><td>✅ Runs on AWS/GCP/Azure (no storage or compute)</td><td>❌ No</td><td>Centralized Cloud-native data warehouse (centralized SaaS)</td><td>💰💰 Medium (SQL interface, but migration cost)</td><td>❌ does not deploy cloud resources</td><td>✅ Manages compute/storage clusters internally</td><td>✅ Query performance, cost monitoring</td><td>✅ SQL/API connectors</td><td><strong>Pure Datawarehouse</strong> with data sharing, marketplace, analytics</td></tr><tr><td><mark style="color:purple;"><strong>Flashgate</strong></mark></td><td>✅ Bridges supporting AWS, Azure, GCP, and all S3 or GCS compatible networks</td><td>✅ Yes, all S3 or GCS compatible networks</td><td>Hybrid neutral control plane (Bridge Nodes + APIs)</td><td>💰 Low (Designed for Vibe Coding)</td><td>❌ does not deploy cloud resources</td><td>✅ quotas, guardrails, repo abstraction</td><td>✅ cost, usage, latency, health across vendors</td><td>✅ unified S3/GCS/Azure/DePIN API (storage) and planned compute API</td><td><strong>Neutral control plane</strong>: security, governance, observability, multi-cloud + DePIN interoperability</td></tr></tbody></table>

### Deployment: Well-Covered by Existing Tools

The “deployment” layer spinning up VMs, provisioning clusters, creating networks and storage buckets is already crowded with powerful, mature tools:

* **Terraform** (and IaC peers like Pulumi, Crossplane) own **infrastructure provisioning** with declarative state management.
* **Anthos, OpenShift, Tanzu** own **multi-cloud Kubernetes orchestration**, letting enterprises deploy and scale containerized workloads consistently.
* The hyperscalers themselves (AWS, GCP, Azure) expose robust deployment APIs, CLIs, and templates.

Because of this, attempting to make Flashgate a deployment orchestrator would both duplicate effort and dilute the project’s unique value. That space is saturated, and the industry has converged on established standards.

### Management & Monitoring: Fragmented

Management (updates, scaling, lifecycle ops) and monitoring (metrics, costs, performance) are partly addressed by providers and orchestrators, but fragmented:

* Each cloud has its own dashboards, APIs, and billing models.
* Anthos, Tanzu, OpenShift, and similar frameworks add some unification, but their observability is **usually limited to Kubernetes workloads.**
* There is **no neutral layer** giving a complete observability across *all resources* (centralized + decentralized, storage first, compute in the future) allowing guardrails like budgets, quotas, or auto-disables.

This leaves developers and enterprises writing glue code and juggling multiple dashboards just to keep usage under control.

### Integration: Flashgate’s Differentiator

Flashgate’s core bet is that **integration is the true pain point**:

* Developers want to use resources (read/write objects, run workloads, access APIs) without caring if they sit in AWS, GCP, Azure, or a DePIN provider.
* Enterprises want **guardrails, observability, and unified security** applied consistently across providers, things the vendors don’t offer natively, because their incentives push toward lock-in.
* By exposing **one neutral API**, Flashgate lets teams integrate with storage (and soon compute) seamlessly. Under the hood, Bridge Nodes translate and secure the requests, so the app developer never sees the complexity.

This is exactly the same logic that made the **S3-compatible API** the lingua franca of object storage, Flashgate extends that principle beyond a single vendor.

### The DePIN Dimension

Filecoin is the proof that decentralized infrastructure can work at scale, but it’s not integrated with enterprise workflows. Like the other DePINs, FIlecoin is monolithic: You must integrate with IPFS and you are stuck with complex consensus.\
Flashgate is the only solutions in this space bringing DePIN into the conversation, but Flashgate’s originality is that it blends it with centralized providers in the **same UX and control plane**. For exemple, once a user receives from any DePin protocol a S3-compatible API, He can seamlessly integrate with it. No friction.\
That means enterprises can hedge between hyperscalers and decentralized operators with **no app-level rewrites**, while applying the same policies and monitoring across both.

### Positioning Takeaways

This makes it easier for you to understand our positioning:

* **Deployment** is owned by tools like Terraform, Anthos, OpenShift, Tanzu (and the clouds themselves).
* **Monitoring** is baked into hyperscalers and orchestrators, but fragmented across providers.
* <mark style="color:purple;">**Integration is where Flashgate is unique**</mark>: a single neutral API for **using** resources, observability built in and allowing unified guardrails, cost controlability, governance, and privacy.
* **Filecoin** and decentralized providers are the only ones introducing a **DePIN (decentralized) dimension**, but Flashgate uniquely blends it with centralized providers in one UX.


# Cloud and AI Gateway

Flashgate’s **Cloud and AI Gateway** is the unified entry point for connecting, governing, and consuming cloud and AI services across your organizations, workspaces, and repositories. It centralizes identities, keys, and usage while providing a consistent API layer for your applications.

## What is the Gateway?

The gateway is an **abstraction layer** that sits between your applications and cloud/AI providers. It simplifies multi-provider integration, enforces your security policies, and exposes consistent endpoints for storage, AI, and network resources.

On the network side, the gateway is backed by **Bridge Nodes**: the physical network layer that connects and surfaces network state. These nodes act as the tangible gateway, providing visibility into network conditions and enabling secure connectivity between your services and external providers.

## Bring your own key (BYOK)

The **bring your own key** model lets you use **your own provider keys** (AWS, GCP, Azure, OpenAI, etc.) while benefiting from centralized governance. Flashgate does not replace your accounts: it **builds on your existing credentials** and helps you organize, monitor, and secure them at scale.

## The 4 core features

The Cloud and AI Gateway is built around four pillars:

* **Cloud Storage**: connect and expose your cloud buckets through a unified interface, with fine-grained access control and usage metrics.
* **AI LLM**: configure AI providers and expose OpenAI-compatible endpoints with centralized governance policies.
* **Repositories**: group storage and AI into a single logical endpoint, and manage repo-scoped access keys.
* **Network**: observe and manage network state, endpoints, and access rules to secure and standardize service consumption, powered by Bridge Nodes.

## Table of contents

| Features                                                                    | Description                                                                   |
| --------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| [**Cloud Storage**](/flashgate-platform/cloud-and-ai-gateway/cloud-storage) | Connect your buckets and manage access centrally, with visibility into usage. |
| [**AI LLM**](/flashgate-platform/cloud-and-ai-gateway/ai-llm)               | Integrate AI providers and expose compatible APIs governed by policies.       |
| [**Repositories**](/flashgate-platform/cloud-and-ai-gateway/repositories)   | A single entry point to combine storage and AI with repo-level keys.          |
| [**Network**](/flashgate-platform/cloud-and-ai-gateway/bridge-nodes)        | Observe network state and manage endpoints and rules, backed by Bridge Nodes. |


# Cloud Storage

Cloud Storage in Flashgate is the object-storage layer of the **Cloud and AI Gateway**. It lets you connect buckets/containers from multiple providers behind one operational model, so storage resources can be consumed consistently by repositories, automation, and AI/LLM workflows.

At a high level:

* A **Bucket** in Flashgate is the representation of a remote vendor’s object storage resource.
* Depending on the provider, this resource can be called a **bucket** (S3, GCS) or a **container** (Azure Blob).
* Flashgate standardizes access to those resources while preserving provider-specific connectivity and identity options.

## What Flashgate supports for buckets and object storage

Flashgate supports object storage resources exposed through:

* **AWS S3** endpoints.
* **S3-compatible** APIs from external or on-prem providers through custom endpoints.
* **Google Cloud Storage (GCS)** endpoints.
* **GCS-compatible** APIs from external or on-prem providers through custom endpoints.
* **Microsoft Azure Blob** storage accounts and containers.

This allows you to build multi-cloud, hybrid, and on-prem storage topologies where repositories can target heterogeneous storage backends from a single gateway layer.

## Buckets, containers, and object storage fundamentals

Object storage is designed around:

* **Objects** (data + metadata),
* grouped in **buckets/containers**,
* addressed through HTTP APIs,
* and controlled through API credentials or delegated identities.

In Flashgate, this is especially useful when your storage resources are used alongside AI/LLM patterns (for example: grounding data, archived corpora, binary artifacts, logs, and generated outputs), because you can connect storage providers with consistent governance and repository-level operations.

## Configure bucket resources

For exact creation fields, provider-specific parameters, access mechanisms, storage-type constraints, and warnings, use the detailed guide:

* [Configure a Bucket](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket)

You can also configure buckets via API:

* [Bucket Management API](/support-reference/platform-api-reference/storage-apis/bucket-management)

## Security and secret encryption

Secret encryption is a platform-wide security principle in Flashgate, not only a Cloud Storage behavior.

For the full model (how secrets are encrypted, when decryption happens, and why this applies to buckets, AI providers, and other connected resources), see:

* [Security and Secret Encryption](/support-reference/security-and-secret-encryption)


# AI LLM

An **LLM (Large Language Model)** is an AI model trained to understand and generate text (and sometimes code, images, etc.). In practice, your application sends a prompt to an LLM provider (e.g., OpenAI, Google, Anthropic), and receives a completion/response.

Flashgate’s **Cloud and AI Gateway** lets you connect these providers **once**, then reuse them across your workspaces and repositories with:

* centralized credential management,
* usage monitoring (tokens, requests),
* and governance through AI Policies.

***

## How AI works in Flashgate

Flashgate’s AI layer combines:

* **AI LLM management** (provider connections),
* **AI Policy** (governance rules),
* **AI API Keys** (scoped keys your apps use to call AI through Flashgate).\
  These policies can be scoped at **organization, workspace, or repository** level.

> In other words: you plug providers in, you govern usage, and your applications call Flashgate with scoped keys.\
> (See Platform API Reference → AI for the full API details.)

***

## 1) AI LLM configurations (connect providers)

An **AI LLM configuration** is a secure connection to an external AI provider (credentials + endpoint + provider type), created **per workspace**.

Typical supported providers include:

* OpenAI-compatible providers
* Google (Gemini)
* Anthropic (Claude)

Flashgate is designed to be **OpenAI-compatible**, which also makes it possible to connect on-prem or decentralized providers that expose an OpenAI-compatible API.

### Key properties and guarantees

* **Centralized configuration**: store and manage provider credentials in one place.
* **Multi-provider**: you can configure multiple providers and switch over time.
* **Security**: credentials are **encrypted at rest** and **never returned in API responses**.
* **Validation**: you can test a configuration to ensure credentials + endpoint work.
* **Monitoring**: usage stats (requests, tokens, policy violations) are available.

***

## 2) Repositories: where AI LLMs become usable by apps

A **Repository (Repo)** is the workspace-level container that groups resources (storage and AI) under a single API interface. From a client perspective, a Repo behaves like **one logical endpoint**:

* you attach one or more AI LLM configurations as resources,
* you choose an API surface to expose,
* and you generate repo-scoped API keys for your applications.

For AI, the Repo exposes an **OpenAI-compatible** endpoint type, and the keys you generate for AI are meant to be used with the AI resources attached to that Repo.

> Important: repo keys are shown only once at creation time; if you lose the secret, you must generate a new key.

***

## 3) Governing AI usage with AI Policies

AI Policies let you define natural-language governance rules such as:

* PII handling,
* security constraints,
* content boundaries,
* and other guardrails.

Policies can be scoped at:

* **Organization**
* **Workspace**
* **Repository**

Actions can include logging, alerting, or blocking (depending on your policy configuration).

***

## 4) Observability & operations

Once your AI LLMs are configured and attached to repos, you can monitor:

* total requests,
* tokens in / tokens out,
* and policy enforcement signals.

Operational best practices:

1. **Validate** configurations after creation or credential updates.
2. **Rotate** provider keys periodically.
3. **Prefer scoped repo keys** for applications (least privilege).
4. **Review stats** regularly to detect spikes or policy violations.
5. Clean up unused configurations to keep workspaces tidy.

***

## Where to go next

* If you need the exact endpoints and payloads, open **Platform API Reference → AI**:
  * AI LLMs (CRUD + validate + stats)
  * AI Policy
  * AI API Keys
* For storage + repo mechanics, see **Cloud Storage** and **Repositories** under Cloud and AI Gateway.

## Security and secret encryption

Secret encryption is a platform-wide security principle in Flashgate, not only a Cloud Storage behavior.

For the full model (how secrets are encrypted, when decryption happens, and why this applies to buckets, AI providers, and other connected resources), see:

* [Security and Secret Encryption](/support-reference/security-and-secret-encryption)


# Repositories

A **Repository** is the unified runtime container in Cloud and AI Gateway. It groups multiple resources under one logical endpoint and one operational surface for access control.

A repository can aggregate:

* **Cloud Storage** resources (S3/GCS/Azure Blob)
* **AI LLM** resources (OpenAI-compatible endpoint type)
* Other supported resource families as the platform evolves

## Why repositories matter

Repositories let your applications:

* consume multi-provider resources behind a consistent endpoint model,
* use repository-scoped API keys instead of account-wide credentials,
* apply governance and permissions at repository scope.

## UI structure

In the **Repositories** section, you typically find:

* **Overview**: high-level repository view and quick navigation.
* **Inventory**: list of repositories and entry point to create/open repositories.
* **API Keys**: centralized list and management view of repository API keys.

## Recommended workflow

1. Start with [Create a Repository](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1/create-a-repository) for naming, endpoint type, and initial resource attachment.
2. Continue with [Configure a Repository](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1/program-with-flashgate) for detailed resource management and API key generation.

{% hint style="info" %}
Detailed creation properties, naming guidance, and key-generation behavior are documented in the two guide pages above to keep this overview page concise.
{% endhint %}

## Secret handling reminder

Repository API secrets are displayed once at key creation and then cannot be retrieved again from the UI. Store them immediately in your secure secret manager and rotate keys if a secret is lost.

Detailed platform behavior is documented in [Security and Secret Encryption](/support-reference/security-and-secret-encryption).

## API references

* [Repository Management APIs](/support-reference/platform-api-reference/repo-management)
* [Repo API Keys (Storage)](/support-reference/platform-api-reference/storage-apis/api_keys)
* [AI API Keys](/support-reference/platform-api-reference/ai-apis/ai-api-keys)


# Network

Bridge nodes are the endpoints of the Flashgate Network, that give access to the different supported APIs. Her, you'll explore:

* [What is a Bridge Node?](#what-is-a-bridge-node)
* [Public Bridge Node](#public-bridge-node)
* [Private Bridge Node](#private-bridge-node)

{% hint style="warning" %}
For testing purposes only, Flashgate has deployed bridge nodes in [the following providers and regions](/support-reference/supported-regions-providers-for-test-bridge-nodes) for testing purposes. Flashgate will offer the capacity to users to deploy their own Flashgate Bridge Nodes in their Cloud tenants to avoid excessive egress costs.
{% endhint %}

{% hint style="danger" %}
AI LLMs is partially supported. Later version will provide all the indicators in this page to understand how to interact with your favorite AI solutions.
{% endhint %}

***

## What is a Bridge Node?

#### Definition

A **Bridge Node** is a Flashgate-hosted (or self-hosted) endpoint that speaks a standard storage API—**S3**, **GCS**, or **Azure Blob**—and transparently translates requests to the underlying bucket/provider you’ve configured via your Repository policy. Each Bridge Node exposes a predictable URL so your apps can keep one client, one credential set, and route across clouds at runtime.

#### **Endpoint pattern**

Bridge Nodes follow:\
`https://<api>-<region>-<provider>.flashback.tech`\
where `<api>` is `s3`, `gcs`, or `blob`, and `<region>`/`<provider>` map to the target location/cloud (e.g., `s3-us-east-1-aws.flashback.tech`).

#### **Why it matters**

Flashgate measures node health and latency so your code can pick the fastest Online Bridge Node (and fail over if it degrades), letting you enforce SLOs like “prefer sub-50 ms reads.” Latency is typically lowest when the Bridge Node is geographically close and on the same cloud as your bucket.

#### **Observability**

Minute-level per-node stats are exposed via `GET /stats/nodes/minute` (optionally filtered by `bucketId`) so you can drive routing decisions and dashboards. The bucket view also surfaces Online/Disconnected/Offline and HeadBucket latency signals.

#### **Security**

Repository API secrets are stored encrypted and are only decrypted in Bridge Node memory; they cannot be recovered later from the UI. Bridge Nodes can be registered to the platform via cryptographic signature verification (RSA) tied to an organization key—no traditional auth required.

#### **Deployment options**

Flashgate runs public Bridge Nodes you can use to get started, and you can also **deploy your own nodes** inside your cloud tenants to reduce egress and keep traffic local.

#### **Quick start**

* Point your S3/GCS/Azure client to a Bridge Node URL and use your **repo-scoped keys**.
* List active nodes and poll `GET /stats/nodes/minute` to rank endpoints by recent latency and availability.
* Cache the chosen endpoint briefly (60–120 s) and invalidate on timeouts/5xx to trigger fast failover.

***

## Public Bridge Node

A Public Node is a Bridge Node that Flashgate runs for you. It exposes standard **S3/GCS/Azure Blob** endpoints under the `*.flashback.tech` pattern, so your apps can talk to **one URL** and reach buckets across AWS, GCP, or Azure without changing SDKs or creds. Flashgate operates and monitors these nodes (latency, health, reachability), making them ideal for **instant onboarding, demos, CI, and cross-cloud routing**. You get zero deploy/ops, smart endpoint selection (pick the fastest/nearest), and a clean upgrade path to **Private Nodes** later if you need stricter network boundaries or to minimize egress.

{% hint style="warning" %}
Flashgate has deployed bridge nodes in [the following providers and regions](/support-reference/supported-regions-providers-for-test-bridge-nodes) for testing purposes.\
Public nodes are recommended for testing purposes but using private nodes is mainly recommended for privacy and cost management.
{% endhint %}

#### Properties

Use the following URL pattern to reach any Bridge Node:

```markup
https://<api>-<region>-<provider>.flashback.tech
```

* **\<api>**
  * `s3` (for S3-compatible access)
  * `gcs` (for GCS-compatible access)
  * `blob` (for Azure Blob access)
* **\<region>**
  * `us-east-1`
  * `eu-central-1`
* **\<provider>**
  * `aws`
  * `gcp`
  * `azure`

**Examples** (region = `us-east-1`, provider = `aws`):

* S3 API: `https://s3-us-east-1-aws.flashback.tech`
* GCS API: `https://gcs-us-east-1-aws.flashback.tech`
* Blob API: `https://blob-us-east-1-aws.flashback.tech`

#### Endpoint Data

Because latency is typically lowest when your Bridge Node is both geographically close and on the same cloud provider as your bucket, it’s best to connect to the node that gives you the fastest response. To help you choose, each Bridge Node publishes real-time stats in the Storage Bucket details view:

* **Status**
  * ⏺ <mark style="color:green;">**Online**</mark> (e.g. “Online 12 ms”) – the node is up and responding in the shown time.
  * ⏺ <mark style="color:orange;">**Disconnected**</mark> – the node attempted authentication but received an unauthorized error.
  * ⏺ <mark style="color:red;">**Offline**</mark> – the node cannot reach the bucket endpoint at all/
* **Latency**\
  Measured in milliseconds by issuing a `HeadBucket` request against your bucket and timing the round-trip.

***

## Private Bridge Node

A **Private Bridge Node** is the same stateless API proxy as a Public Node—speaking **S3**, **GCS**, or **Azure Blob**—but **runs inside your own cloud account/VPC/VNet**. It gives you the same one-client, multi-cloud abstraction while keeping data paths private, reducing egress, and letting you enforce your own network and compliance controls.

#### How it’s reached

* **Internal-only (recommended):** Place the node on a private subnet and expose it via an internal load balancer, service mesh, or PrivateLink/Private Service Connect equivalent.
* **Custom domain (optional):** Point a DNS name you control (e.g., `s3.internal.example.com`) to the node.
* **Protocol surface:** The node exposes the same APIs as Public Nodes:
  * `s3` (S3-compatible)
  * `gcs` (GCS-compatible)
  * `blob` (Azure Blob–compatible)

> Tip: keep your app’s SDK config identical to public usage—only the **endpoint/base URL** changes to your private address.

#### Keys & auth

* Use your **Repository-scoped access key** and **secret** (the same pair you’d use against a Public Node).
* Keys are validated by the node against your Flashgate repo; bucket routing still follows your **Repository policy**.
* Secrets remain encrypted at rest and are only decrypted in node memory during request handling.

#### Routing & performance

* The Private Node applies the same provider/bucket routing rules as your Repository.
* For lowest latency and lowest egress, **co-locate** each Private Node with the buckets it primarily serves (same cloud + region).
* You can run multiple Private Nodes (e.g., one per region) and choose the nearest in your app’s config or via your own health-based picker.

#### Health & status (what you’ll see in Flashgate)

Private Nodes report into the platform just like Public Nodes, so the **Storage Bucket** view will show per-node status and latency:

* **Online** (e.g., “Online 12 ms”): node is up; round-trip based on a `HeadBucket` probe.
* **Disconnected**: node reached Flashgate but failed auth (check repo keys/registration).
* **Offline**: node can’t reach the target bucket endpoint (check routing, VPC egress, DNS, firewall, or cloud endpoint health).\
  Latency is measured in **milliseconds** using periodic `HeadBucket` checks.

#### Registration & security

* Register the node to your organization so it can fetch repo metadata and emit health metrics.
* Run it under the minimum network policy required to reach:
  1. your target storage endpoints (AWS/GCP/Azure as configured), and
  2. Flashgate’s control plane for secure heartbeats/metrics.
* Lock down inbound access to your app networks only (security groups/NSGs, firewall, mesh policy).

#### Deployment patterns

* **AWS:** ECS/Fargate or EKS behind an **NLB/ALB**; optionally expose through **VPC Endpoint/PrivateLink**.
* **GCP:** GKE or managed instance group behind **Internal HTTP(S) LB** or **PSC**.
* **Azure:** AKS or VMSS behind **Internal Load Balancer** or **Private Link Service**.
* **Bare metal/DC:** Any container orchestrator; front with your internal L4/L7 proxy.

#### Quick start

1. **Deploy** the Bridge Node container in your VPC/VNet and put it behind an internal LB. (Tutorial soon)
2. **Register** it to your Flashgate organization (so health + stats appear).
3. **Point your SDK** to the node’s private URL:
   * S3 clients: set `endpoint_url` to your private host; keep `accessKeyId/secretAccessKey` as repo keys.
   * GCS/Azure clients: set the base URL similarly; use the repo-scoped credentials.
4. **Verify health** in Flashgate: status should be **Online** with a low `HeadBucket` latency.
5. **Lock down** inbound ACLs and outbound routes (only the storage endpoints and Flashgate control plane).

#### Troubleshooting

* **Disconnected:** rotate repo keys or re-register the node.
* **Offline:** check DNS, NAT/egress rules, service endpoints, or cloud-to-cloud firewall.
* **High latency:** move the node closer to the bucket region, or provision one Private Node per major region and choose the nearest.


# Organization

The **Organization** area is the control center for governance, access, operations, and cost management across Flashgate.

If the **Cloud and AI Gateway** is where you connect resources, the Organization area is where you:

* define who can do what,
* structure work through teams and workspaces,
* enforce AI guardrails,
* track usage and risks,
* and manage subscription and credits.

## Why it matters

As your company scales from a few users to many teams and repositories, Organization features help you keep one shared operating model:

1. **Identity & access** (members, roles, and permissions)
2. **Resource structure** (workspaces and repositories)
3. **Governance** (policies at org/workspace/repository scope)
4. **Observability** (usage, cost, and policy signals)
5. **Financial control** (billing plans, credit consumption, top-ups)

## What you can manage in Organization

| Section                                                                       | What it is for                                                               |
| ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| [Organization Profile](/flashgate-platform/organization/organization-profile) | Edit organization metadata and admin-level settings.                         |
| [Teams](/flashgate-platform/organization/teams)                               | Invite members, remove access, and manage roles/permissions.                 |
| [Workspaces](/flashgate-platform/organization/workspaces)                     | Create and manage workspaces as operational domains under your organization. |
| [Policies](/flashgate-platform/organization/policies)                         | Define AI guardrails and enforcement behavior at multiple scopes.            |
| [Instances & Connected Resources](broken://pages/OzoMezkJWYbYzpFdJPyu)        | Operate gateway instances and verify connected resources.                    |
| [Statistics](/flashgate-platform/organization/statistics)                     | Analyze infrastructure, AI, storage, private chat, and policy metrics.       |
| [Billing & Credits](/flashgate-platform/organization/billing-and-credits)     | Manage plan, credit budget, top-ups, and consumption rates.                  |

## Related API references

For implementation details and endpoint contracts:

* [Organization Management API](/support-reference/platform-api-reference/organization)
* [Workspace API](/support-reference/platform-api-reference/workspace)
* [AI Policy API](/support-reference/platform-api-reference/ai-apis/ai-policy)
* [Statistics API](/support-reference/platform-api-reference/statistics)
* [Credits API](/support-reference/platform-api-reference/credits)
* [Subscriptions API](/support-reference/platform-api-reference/subscriptions)


# Organization Profile

The **Organization Profile** is where admins maintain core company information used across the platform.

## What you can edit

Typical editable fields include:

* organization name,
* legal or billing identity details,
* operational metadata used for administration,
* organization-wide settings exposed in the platform.

## Who can edit

Only high-privilege roles should edit profile settings (typically **ADMINISTRATOR** or **OWNER**).

## Best practices

* Keep organization metadata up to date to reduce billing and compliance issues.
* Restrict profile-edit permissions to a small admin group.
* Review settings after ownership or finance changes.

## API mapping

* `GET /organization/{orgId}`
* `PUT /organization/{orgId}`

See: [Organization Management API](/support-reference/platform-api-reference/organization)


# Teams

The **Teams** section helps you control who can access your organization, and what each member can do.

## Team management capabilities

In Teams, you can:

* view all organization members,
* invite/add new members,
* remove members,
* update member role and access scope,
* control workspace-level access,
* control private chat eligibility based on permissions.

## Typical role model

Flashgate uses role-based access control. Common role levels include:

* **USER**: basic usage
* **BILLING**: billing/subscription operations
* **WORKSPACES**: workspace and team operations
* **ADMINISTRATOR**: administrative settings and user management
* **OWNER**: full control

## Workspace and private chat access

For production setups, team governance should include:

* explicit workspace assignment,
* least-privilege role configuration,
* periodic review of access to repositories and private chat environments.

## Operational recommendations

* Add members with the minimum role needed.
* Use ADMINISTRATOR/OWNER roles sparingly.
* Remove inactive users quickly.
* Re-check permissions after org restructures.

## API mapping

* `GET /organization/users`
* `POST /organization/users`
* `GET /organization/users/{userId}`
* `PUT /organization/users/{userId}`
* `DELETE /organization/users/{userId}`
* `POST /organization/users/{userId}/activate`

See: [Organization Management API](/support-reference/platform-api-reference/organization)


# Workspaces

A **Workspace** is an operational domain inside your organization. It groups people, repositories, and connected resources for a specific team, product, or environment.

## How workspaces relate to the gateway

The Cloud and AI Gateway is an abstraction layer, and in practice your organization is usually structured into **multiple workspaces**. Each workspace can contain repositories, and those repositories attach cloud storage and AI/LLM resources.

## What you can do in Workspace management

* list all workspaces you can access,
* create a new workspace,
* edit workspace metadata/configuration,
* remove a workspace,
* manage workspace-level rights (read/write/admin, depending on role).

## Recommended structure patterns

* Split by environment: `dev`, `staging`, `prod`
* Split by business domain: `search`, `assistant`, `analytics`
* Split by security boundary: regulated vs non-regulated workloads

## Why this matters

Good workspace design improves:

* security isolation,
* policy clarity,
* cost attribution,
* and observability granularity.

## API mapping

* `POST /workspace`
* `GET /workspace`
* `GET /workspace/{id}`
* `PUT /workspace/{id}`
* `DELETE /workspace/{id}`

See: [Workspace API](/support-reference/platform-api-reference/workspace)


# Policies

The **Policies** section is where your organization defines AI governance and safety rules.

## Policy scopes

Policies can be defined at three levels:

* **Organization scope** (global defaults)
* **Workspace scope** (team or environment-specific)
* **Repository scope** (fine-grained, endpoint-level control)

## What policies are used for

Policies are AI guardrails for LLM traffic and AI usage. They can be used to:

* reduce privacy/compliance risk,
* detect or block sensitive data exposure,
* enforce usage constraints,
* standardize behavior across teams.

Examples include:

* PII handling constraints,
* redaction requirements,
* disallowed content classes,
* logging and alerting behavior.

## Policy building blocks

A robust policy usually includes:

* a **scope** (where it applies),
* a **risk level**,
* one or more **actions** (log, alert, block, etc.),
* a clear natural-language rule describing intended behavior.

## Relationship with Private Chat

Private Chat traffic that uses repository AI resources is subject to policy evaluation. This gives admins visibility and control over how AI interactions are handled across the organization.

## API mapping

See: [AI Policy API](/support-reference/platform-api-reference/ai-apis/ai-policy)


# Statistics

The **Statistics** section gives organizations deep observability across infrastructure, AI usage, private chat activity, and policy events.

## What you can analyze

### Gateway and resource usage

Track platform-wide and scoped metrics, including:

* credit consumption,
* AI/LLM usage,
* storage and data transfer,
* uploaded and downloaded data volume,
* token usage and trend comparisons over time.

### Private Chat analytics

Review how teams use private chat:

* activity levels,
* conversation and prompt volume,
* token consumption over time,
* workspace/repository distribution.

### Policy analytics

Admins can inspect policy-level signals such as:

* policy trigger counts,
* violation/breach indicators,
* risk trends,
* affected scopes and users.

This helps security and governance teams refine AI safety posture.

## Why this section is critical

Statistics convert raw operations into decisions:

* optimize infrastructure and provider mix,
* detect anomalies early,
* tune policies with evidence,
* and improve cost predictability.

## API mapping

See: [Statistics API](/support-reference/platform-api-reference/statistics)


# Billing & Credits

The **Billing & Credits** section lets you manage subscription plans, monitor credit burn, and purchase additional credit packs.

## Billing management

From this section, authorized users can:

* view current subscription,
* change organization plan,
* manage billing details and payments,
* track plan renewals and consumption behavior.

## Credit model overview

Flashgate uses a **credit-based consumption system**. Credits are consumed based on node type and operation profile.

### Consumption rates

#### Public nodes

* **Storage egress**: `10 credits / GB`
* **AI/LLM tokens out**: `0.001 credit / token out`

#### Private nodes

* **Storage egress**: `1 credit / GB`
* **AI/LLM tokens out**: `0.00005 credit / token out`

> Public-node traffic generally consumes credits faster than private-node traffic.

## Plan credit allocations

### Individual

* `10 credits/month`

### Organization Free

* `40 credits/month`
* No monthly/annual paid billing cycle

### Starter

* `1,100 credits/month` or `15,000 credits/year`
* `$100/month` or `$1,000/year`

### Growth

* `9,500 credits/month` or `130,000 credits/year`
* `$300/month` or `$3,000/year`

### Scale

* `89,000 credits/month` or `1,125,000 credits/year`
* `$1,000/month` or `$10,000/year`

## Credit pack top-ups

You can add extra credits with packs (up to **3 packs per month**):

* `+100 credits` for `$20`
* `+500 credits` for `$50`
* `+1,000 credits` for `$100`

## Upgrade and downgrade behavior

* On upgrade: you receive plan credits for the selected billing periodicity.
* On downgrade: already allocated credits for the paid/prepaid period are preserved.
* Example: if a monthly period is already paid, credits remain available during that period.

## API mapping

* Credits: [Credits API](/support-reference/platform-api-reference/credits)
* Subscription & billing: [Subscriptions API](/support-reference/platform-api-reference/subscriptions)


# Private Chat

**Private Chat** is Flashgate’s text-to-text conversational interface for secure interaction with AI models connected through the Cloud and AI Gateway.

It is designed for organizations that want centralized governance, repository-scoped AI access, and usage observability.

## What Private Chat is

Private Chat is a standard multi-turn chat experience where users can:

* select an environment,
* prompt available AI models,
* continue context-aware conversations,
* and monitor usage over time.

## Required setup before using Private Chat

Private Chat depends on your gateway setup. Before using it, you must have:

1. an **AI/LLM resource** configured,
2. attached to a **repository**,
3. and that repository inside a **workspace**.

Without this chain (workspace → repository → AI resource), Private Chat cannot execute model calls.

## Environment selection model

Before starting a conversation, users select an environment that maps to:

* **Workspace + Repository**

This determines:

* which providers/models are available,
* which policies are enforced,
* and which permissions apply.

## Model availability

Private Chat exposes models from the providers connected to the selected repository.

Example:

* if an OpenAI resource is connected to the selected repository, users can access OpenAI models available through that configured endpoint.

This same logic applies to other connected providers.

## Usage and consumption

Private Chat consumes underlying provider resources through your Flashgate setup. Depending on your configuration and credits, organizations can optimize cost by routing usage through preferred providers or existing cloud credits.

## Built-in visibility

Private Chat includes quick usage visibility (for example, recent consumption windows such as last 7 days), while organization-wide analytics are available in the **Organization → Statistics** pages.

## Governance and policy enforcement

Private Chat usage is governed by policy scopes defined in the platform:

* organization,
* workspace,
* repository.

This allows privacy and compliance controls to apply consistently to conversational traffic.

## Current and upcoming capabilities

Private Chat currently supports core conversation workflows and model interaction. Roadmap-oriented capabilities include:

* longer-term memory behavior,
* deeper storage-backed memory,
* richer agent-based interactions across conversations.

## API mapping

See: [Conversation API](/support-reference/platform-api-reference/conversation-api)


# ISP Market

{% hint style="success" %}
**With a primary focus on storage**, we are designed to be the solution of choice for companies demanding higher controlability while higher spectrum of decentralized offers. Flashgate helps reduce investigation time across different providers while offering to providers an easy marketplace to propose their resources.
{% endhint %}

This section explains how providers and consumers connect through the **ISP Market**, Flashgate's decentralized cloud and AI resource marketplace. By leveraging orchestrators, data-unit level provisioning, and policy-based monitoring, the platform ensures transparency, trust, and operational efficiency.

Providers (also called Unit Providers) offer capacity that is registered and certified in the ISP Market to meet predefined quality standards. Consumers (also called Unit Consumers), including businesses and individuals, allocate these Data Units through orchestrators that manage reservations, SLAs, and payments.

At the network's core lies the **Orchestrator Smart Contract**, which acts as the trustless coordinator of the marketplace. It ensures SLA compliance, tracks quality-of-service (QoS) metrics, manages payments, and enforces penalties for non-compliance. Supported by oracles, the network bridges on-chain and off-chain data for real-time insights. At the API level, the platform now prioritizes **Data Unit-compatible access credentials** (such as S3-compatible keys for storage units) rather than a single universal API standard.

## Section Table

<table><thead><tr><th width="227">Section</th><th>Summary</th></tr></thead><tbody><tr><td><a href="/pages/dDEorGAHR82Wzpe71lOR"><strong>Overview</strong></a></td><td><em>Introduction to the core layers of the ISP Market.</em></td></tr><tr><td><a href="/pages/9mRHvelcue2I3YlJjYR6"><strong>Data Unit</strong></a></td><td><em>How providers publish Data Units and how consumers allocate them.</em></td></tr><tr><td><a href="/pages/SpEBjZQncx5IWSJOZdKZ"><strong>Orchestrator</strong></a></td><td><em>Overview of the smart-contract orchestration layer and lifecycle management.</em></td></tr><tr><td><a href="/pages/sq8N6I5jiI7xZDEi4BTs"><strong>API Interactions</strong></a></td><td><em>How suite APIs and Data Unit-compatible credentials are used in practice.</em></td></tr><tr><td><a href="/pages/lwrEJaWn4nUONobmDbZx"><strong>SLAs and QoS metrics</strong></a></td><td><em>How SLAs and QoS metrics define trust and compliance across the market.</em></td></tr><tr><td><a href="/pages/n1JvjKeyho75DxaFNoFG"><strong>Reputation System</strong></a></td><td><em>How provider reputation evolves from SLA and QoS performance.</em></td></tr></tbody></table>


# Overview

## Architecture Diagram

```mermaid
flowchart TB
    C[Clients - Developers and Apps] --> A[Flashgate API and SDK]

    subgraph FP[Flashgate Platform]
        M[ISP Market - Offerings Pricing and SLAs]
        O[Orchestrator - Provisioning and Allocation]
        P[Policy and Governance - Quotas Budgets Routing]
        T[Metrics & Telemetry]
    end

    subgraph PR[Providers]
        S3[AWS S3]
        GCS[GCP GCS]
        DS[Decentralized Storage - Filecoin and Storj]
    end

    A --> M
    A --> O
    A --> P
    O -->|provision / allocate| S3
    O -->|provision / allocate| GCS
    O -->|provision / allocate| DS
    S3 -->|metrics| T
    GCS -->|metrics| T
    DS -->|metrics| T
    P -->|decisions| O

    subgraph DU[Data Unit states]
        D1[Available] --> D2[Reserved] --> D3[In-use] --> D4[Maintenance] --> D5[Decommissioned]
    end
```

***

The rise of Web3 and distributed infrastructure is reshaping how storage and AI resources are discovered and consumed. The **ISP Market** is designed as a decentralized cloud and AI resource marketplace that connects **Consumers** and **Providers** with transparent coordination between off-chain services and on-chain enforcement.

***

## **ISP Market: Decentralized Cloud and AI Resource Marketplace**

The ISP Market manages key operations, including SLA alignment, allocation workflows, quality verification, and payment enforcement.

To ensure flexibility, the solution supports both fiat and cryptocurrency payments (BTC, XLM, STRK, ALGO, and others). Providers and Consumers can use the ecosystem that best fits their operations, while the platform handles orchestration and settlement logic.

**Smart Contract Orchestrators**

Orchestrators communicate with the ISP Market control plane, ensuring SLAs, payments, and quality metrics are synchronized and enforced.

* **Orchestrator for Providers**: Manages published Data Units, SLA commitments, and quality monitoring.
* **Orchestrator for Consumers**: Handles reservations, payment flows, and data-access rights for allocated units.

**ISP Market Core Functions**

The marketplace core integrates operational tooling to simplify provider onboarding and consumer adoption:

* **Monitor:** Tracks Provider and Data Unit performance signals used for SLA and reputation decisions.
* **Registry:** Maintains certified Providers and Consumers meeting market compliance requirements.
* **Marketplace:** Public discovery layer where Consumers compare Data Units, capabilities, and reliability indicators.
* **Oracles:** Validation network that reports SLA/QoS observations to orchestrators and smart contracts.

***

## **Consumers (or Unit Consumers)**

* Individuals, organizations, or applications requiring storage and AI/compute resources.
* Allocate Data Units through the marketplace and then consume them with generated credentials compatible with the allocated unit type.

SLA payments depend on requested resources, reservation duration, provider profile, redundancy, QoS targets, and allocation terms.

***

## **Providers (or Unit Providers)**

Providers with storage and/or compute infrastructure can publish Data Units to the marketplace. Payments can be streamed to Provider wallets according to orchestration rules and verified service delivery.

* Offer storage and/or compute infrastructure by submitting Data Units to the marketplace.
* Commit to declared quality and availability standards.
* Maintain certification and reporting status to remain discoverable.

### Bridge Node

The Bridge Node remains a key infrastructure component for provider integration:

* Manages data transfer paths between Consumer and Provider using compatible protocols (e.g., S3/GCS for storage scenarios).
* Sends performance reports to oracle pipelines for SLA/QoS verification.

Typical provisioning flow:

* The Provider installs the Bridge Node locally. A registration signal is sent to the platform and an installation secret is generated.
* The Provider connects a wallet to claim the Bridge Node and authorize collateralized operations.
* Once registered, the Provider can submit Data Units and make them available for reservation in the ISP Market.


# Data Unit

## Architecture Diagram

{% @mermaid/diagram content="stateDiagram-v2
\[\*] --> Available: Provider registers unit
Available --> Reserved: Consumer reserves
Reserved --> InUse: Orchestrator allocates
InUse --> Maintenance: Provider/Orchestrator schedules maintenance
Maintenance --> Available: Maintenance completed
Available --> Decommissioned: Provider retires
Reserved --> Decommissioned: Provider retires
InUse --> Decommissioned: Provider retires" %}

{% @mermaid/diagram content="flowchart TB
subgraph M\[Data Unit Metadata]
ID\[id]
CAP\[capacity]
REG\[region]
PROV\[provider]
SLA\[SLA]
PRC\[price]
ST\[status]
end

```
Provider -->|registers| Market
Consumer -->|reserves| Market
Market -->|reservation event| Orchestrator
Orchestrator -->|allocates| Consumer" %}
```

***

## **Data Unit: What is it?**

The data unit is not only a storage capacity or compute service offered by the provider but provides additional information such as the quality of services, the geographical location, and more. Each data unit supports multiple reservations (e.g., Reservation 1, Reservation 2, Reservation 3), which represent allocations made by consumers for specific data storage needs.

This elementary reservation is to build a system where the user controls their expenses and their needs. At the same time, it ensures the Providers monitor more efficiently the security and the distribution of data in its infrastructure. By extension, this can enable Providers to supply unused capacity from their infrastructure.

## Steps of the Data Unit Allocation

{% stepper %}
{% step %}
**Initial Submission**

**Each provider has specific "Data Units,"** representing discrete storage capacities or compute services (e.g., S3-compatible, GCS-compatible, or other certified protocols). **Providers submit their Data Units through the ISP Market suite APIs** to make their services available for reservation. This offer will then be submitted in the smart contracts by waiting for the allocation by a Consumer.

The submission of a deal requires the payment of [Unit Deal Submission Fees](https://github.com/flashbacknetwork/flashback-usermanual/blob/main/flashback-platform/tokenomics.md). The Provider may choose to pay additional fees called [Unit Priority Fees](https://github.com/flashbacknetwork/flashback-usermanual/blob/main/flashback-platform/tokenomics.md).
{% endstep %}

{% step %}
**Allocation by Consumer**

Consumer allocation is a two-step process:

* **Selection**: This involves choosing from a list of possible Data Units in the Marketplace.
* **Payment**: Once a Data Unit has been selected, the Consumer can pay for the Data Unit and then receive Data Unit-compatible credentials to start usage (for example S3-compatible credentials for storage units).
  {% endstep %}

{% step %}
**Consumption of the Data Unit**

Using the Data Unit means consuming the allocated resource with the generated credentials and endpoint information returned by the marketplace interface or APIs. During use, the Bridge Node returns performance information to the Oracles that adds to the smart contracts to determine the Reputation Score.
{% endstep %}

{% step %}
**Data Unit Closing**

The end of a Data Unit occurs when the period of use comes to an end, or following voluntary termination by the Consumer or Provider. The payment is executed and [tokenomics](https://github.com/flashbacknetwork/flashback-usermanual/blob/main/flashback-platform/tokenomics.md) is applied.
{% endstep %}
{% endstepper %}

***

## **Interactions Between Elements**

1. **Providers ↔ Orchestrator**:
   * Providers register data units and agree to SLAs managed by the Orchestrator. Based on performance, they receive scoring and incentives.
2. **Consumers ↔ Orchestrator**:
   * Consumers reserve storage and make payments via the Orchestrator, which ensures QoS and compliance with SLAs.
3. **Consumers ↔ Platform ↔ Providers**:
   * Through the platform, consumers directly interact with allocated Data Units using the compatible protocol for that unit.
4. **Tokenomics Layer**:
   * Integrated into the Orchestrator, it manages payments from consumers, rewards for providers, and penalties for non-compliance or failure. This is a long-term feature that we are improving currently in our development iterations.


# Orchestrator

## Architecture Diagram

```mermaid
flowchart LR
    subgraph I[Inputs]
        D[Demand - Requests]
        P[Policies - Quotas and Budgets]
        S[SLAs/QoS Targets]
        T[Telemetry - Latency Cost Capacity]
    end

    subgraph DE[Decision Engine]
        N[Normalization]
        SC[Scoring & Provider Selection]
        PL[Placement / Allocation]
        MP[Migration Planner]
    end

    subgraph EX[Execution]
        PA[Provider Adapters]
        PR[Provisioning / Allocation]
        RU[Routing & Configuration Updates]
    end

    subgraph O[Outputs]
        AR[Allocation Result]
        AL[Audit Log]
        ME[Metrics Events]
    end

    D --> N
    P --> N
    S --> N
    T --> N
    N --> SC --> PL --> MP
    MP --> PA --> PR --> RU
    PR --> AR
    RU --> AL
    PR --> ME
    T --> ME
```

***

The architecture below represents the core logic integrated into smart contracts, acting as an on-chain and trustless orchestrator for the decentralized network of Consumers and Providers. The **Orchestrator** is a smart contract. It is the backbone of the ecosystem, ensuring transparency, compliance, and fair financial transactions through tokenomics. It is critical in maintaining trust and reliability between providers and consumers.

The orchestrator will be deployed on other blockchains and other promising ecosystems. This multi-chain approach allows providers and clients to select the ecosystem they prefer and to optimize their costs and performances by balancing with the networks' load.

Here is the current integration status:

* Stellar (testnet),
* Suite API integrations for Data Unit-compatible access flows (rolling deployment).

***

## **Management of Payments**

The smart contract is the best decentralized technology to support payments and other escrow-like services. In ISP Market operations, smart contracts are used for payment management, traceability, and compliance. It manages the financial and operational aspects of the ecosystem, including:

* **Escrow**: Holds payments securely until conditions in the Service Level Agreements (SLAs) are fulfilled. SLAs must properly specify the conditions of payments, and the Flashgate platform allows for the best agreements.
* **Pricing**: Determines the cost of services, ensuring fairness and market-driven adjustments. Providers must dynamically adapt their pricing according to their resources and services. The integration of AI-driven pricing mechanisms is recommended, and Flashgate will propose some of them.
* **Slashing:** Penalizes data providers or consumers who violate SLAs or fail to meet quality standards. This mechanism is essential to guaranteeing a healthy ecosystem. Meanwhile, the Flashgate platform will be a possible provider intermediary to solve disputes.

***

## **More About Data Units**

Data units represent the storage resources (e.g., storage servers or systems) or compute resources (in future releases) managed by the data providers. Like the sectors in Filecoin, the providers will commit their available spaces with the QoS specifications attached to every data unit. Data units are tracked and managed via reservations, ensuring efficient allocation and availability. There are 4 different states for a data unit:

* **Reserved**: Data sector allocated but not yet in use. It allows the providers to allocate and support the best quality of services. The providers may still decide on the allocation for a user, and then, have the freedom of doing the best business.
* **In Use**: This state means it is actively storing data for consumers.
* **Maintenance**: Undergoing updates or repairs of the data unit which is fundamental to ensure a good quality of services.
* **Decommissioning**: Being removed from the active pool of resources. This state is mainly because the smart contract is memorizing all the data units and then, the decommissioning is needed to not use the data unit again.

***

## **Interactions**

1. **Providers ↔ SLAs ↔ Orchestrator**:
   * Providers register their resources and agree to SLAs enforced by the orchestrator.
   * QoS metrics are monitored to ensure compliance and penalties (slashing) are applied for breaches.
2. **Consumers ↔ Scoring ↔ Orchestrator**:
   * Consumers use the scoring system to select reliable providers.
   * Payments are handled via the payment module (escrow ensures funds are secure until SLAs are fulfilled).
3. **Orchestrator ↔ Data Units**:
   * The orchestrator tracks and manages data units through their lifecycle (reserved, in use, maintenance, decommissioning).
   * Ensures optimal resource utilization and availability for consumers.


# API Interactions

## Architecture Diagram

```mermaid
sequenceDiagram
    participant Client
    participant API as Flashgate API
    participant Market as Market Service
    participant Orch as Orchestrator
    participant Adapter as Provider Adapter
    participant Provider
    participant Metrics as Metrics Service

    Client->>API: GET /market/offerings
    API->>Market: Query offerings
    Market-->>API: Offerings list
    API-->>Client: 200 Offerings

    Client->>API: POST /allocations/reserve
    API->>Market: Reserve Data Unit
    Market->>Orch: Reservation event
    Orch->>Adapter: Provision / allocate request
    Adapter->>Provider: Allocate Data Unit
    Provider-->>Adapter: Allocation confirmed
    Adapter-->>Orch: Allocation result
    Orch-->>API: Allocation status
    API-->>Client: 202 Reserved / Allocating

    Provider->>Metrics: Push telemetry
    Orch->>Metrics: Pull metrics and health

    Client->>API: GET /allocations/{id}
    API->>Orch: Read allocation status
    Orch-->>API: Status and routing details
    API-->>Client: 200 Allocation status
```

***

## **Oracles**

Oracles bridge on-chain and off-chain data by providing real-time verification signals to orchestrators (for example integrity checks, usage telemetry, pricing updates, and SLA evidence). They act as trusted validation intermediaries for service quality.

***

## **Suite API Model (Data Unit-Centric)**

The ISP Market no longer assumes one universal "standard API" for every resource type. Instead, API interactions are centered around the **allocated Data Unit** and its compatible access model.

* **Allocation-first flow**:
  * A Consumer selects and pays for a Data Unit in the marketplace.
  * After allocation, the platform generates credentials tied to that Data Unit.
* **Protocol compatibility by unit type**:
  * Storage Data Units can generate **S3-compatible keys** (and compatible endpoint details).
  * Other Data Unit categories can expose their own compatible access patterns through the Suite API layer.
* **Security scope**:
  * Credentials are scoped to the purchased allocation and lifecycle.
  * Access can be rotated/revoked based on policy, SLA state, or expiration.

This model gives Providers flexibility to expose resources with clear compatibility constraints, while giving Consumers an operational experience aligned with the selected unit.

***

## **Interactions Between Layers**

1. **Providers ↔ Suite APIs ↔ Orchestrator**:
   * Providers register Data Units and supported compatibility profiles.
   * The Orchestrator tracks lifecycle states and enforces policy conditions.
2. **Consumers ↔ Suite APIs ↔ Orchestrator**:
   * Consumers allocate and pay for a Data Unit.
   * The platform issues Data Unit-compatible credentials after successful allocation.
3. **Oracles ↔ Orchestrator ↔ Suite APIs**:
   * Oracles submit validated QoS/SLA evidence.
   * Orchestrator decisions can impact API access state (active, restricted, expired).

***

## **Practical Note for Storage Units**

For storage-focused Data Units, the default operational pattern is:

1. Select a storage Data Unit in ISP Market.
2. Purchase/allocate the Data Unit.
3. Receive generated S3-compatible credentials and endpoint details.
4. Interact directly with the allocated storage unit using these credentials.

As new Data Unit types are introduced, the same allocation-first principle applies, with compatibility determined by each unit profile.


# SLAs and QoS Metrics

The Service Level Agreements (SLAs) and Quality of Service (QoS) metrics are used to evaluate and monitor providers.

{% hint style="success" %}
With **a primary focus on storage**, we are designed to be the solution of choice for companies demanding higher controlbaility while higher spectrum of decentralized offers. Flashgate helps reduce investigation time across different providers while offering to providers an easy marketplace to propose their resources.
{% endhint %}

These metrics ensure a consistent and reliable experience for consumers while providing transparency and accountability for providers.

## SLA Definitions

The following SLA parameters define the minimum standards providers must meet. The ISP Market asks consumers to define target SLA values when allocating a Data Unit. Providers can accept or decline allocations based on these terms. Conversely, providers can publish Data Units with predefined SLA profiles that consumers can select directly.

<table><thead><tr><th>Key Metrics</th><th width="499">Definitions</th></tr></thead><tbody><tr><td><strong>Latency</strong></td><td><p>The time it takes to complete a read or write operation.</p><p><strong>Example</strong>: Maximum average latency of <strong>50ms</strong> for read/write operations</p></td></tr><tr><td><strong>Upload Speed</strong></td><td><p>The speed at which data can be uploaded to the storage service.</p><p><strong>Example</strong>: Minimum speed of <strong>10 MB/s</strong> for uploads of files <strong>1 GB or smaller</strong>.</p></td></tr><tr><td><strong>Download Speed</strong></td><td><p>The speed at which data can be downloaded from the storage service.</p><p><strong>Example</strong>: Minimum speed of <strong>20 MB/s</strong> for downloads of files <strong>1 GB or smaller</strong>.</p></td></tr><tr><td><strong>Uptime</strong></td><td><p>The percentage of time the storage service is operational and accessible.</p><p><strong>Example</strong>: <strong>99.95% uptime</strong> over a rolling 30-day period.</p></td></tr><tr><td><strong>Error Rate</strong></td><td><p>The proportion of failed operations (e.g., upload, download, or delete) compared to the total operations.</p><p><strong>Example</strong>: Less than <strong>0.01% failed operations</strong> per month.</p></td></tr></tbody></table>

***

## QoS Records

The QoS records serve as the backbone for evaluating SLAs. These records are continuously generated through monitoring and probing mechanisms.

#### **Structure of QoS Records**

Each QoS record consists of the following fields:

* **Timestamp**: The exact time when the record was created.
* **ID**: A unique identifier for the provider or the consumer.
* **Operation Type**: The type of operation being measured (e.g., read, write, upload, download).
* **Latency**: Measured latency for the operation.
* **Throughput**: Upload or download speed, depending on the operation type.
* **Success Status**: A flag indicating whether the operation succeeded or failed.
* **Error Details** (if applicable): A description of the error, if the operation failed.

#### **Data Collection Process**

QoS data is collected through a combination of:

1. **Probing Operations**: Automated test operations reported to the platform where the consumers and providers must report their QoS records. The report will support custom period of reports but it must be equal of lower than 24 hours between reports.
2. **System Metrics**: Real-time monitoring of uptime and operational logs.

#### **High-Level Workflow**

1. **Probing**: Scheduled reports that contains metrics such as read, write, upload, and download operations at regular intervals.
2. **Measurement**: Each operation records its latency, throughput, and success status from the consumer and providers.
3. **Aggregation**: QoS records are aggregated over time to calculate averages, percentages, and trends.
4. **Validation**: Aggregated data is validated against SLA requirements found in the smart contract to determine compliance.
5. **Storage**: All QoS records are securely stored in a time-series database for long-term analysis.

#### **Reporting**

Summarized QoS rolling data is sent to the Smart Contract for on-chain enforcement and platform visibility.

Apart from that, other external mechanisms can be implemented to generate and send regular SLA compliance reports to Providers based on custom periods.

The summarized data includes:

* Average latency, upload speed, and download speed over the reporting period.
* Uptime percentage.
* Error rate statistics.

## Enforcement

Failure to meet SLA requirements may result in penalties or reduced [reputation scores](/flashgate-platform/isp-market/reputation-scores). Consumers and providers are encouraged to consistently monitor their performance and address any deficiencies proactively.


# Reputation Scores

The reputation system ranks providers based on objective performance metrics. The system ensures transparency and incentivizes providers to maintain high-quality service.

## Reputation Score

The **Reputation Score** reflects a provider's adherence to SLAs and performance metrics. It is calculated using data collected from QoS records and SLA compliance checks.

Providers start with a baseline score of **50 points** with a minimum of **0 points** and a maximum of **100 points**.

The table summarizes the criteria per Data Unit for the Provider.

<table><thead><tr><th width="482.7999267578125">Criteria per Data Unit</th><th>Score</th></tr></thead><tbody><tr><td>Report all SLA requirements on time.</td><td><strong>+1 point</strong></td></tr><tr><td>Meet all SLA requirements.</td><td><strong>+2 points</strong></td></tr><tr><td>Performances above 20% of the SLA requirements.</td><td><strong>+3 points</strong></td></tr><tr><td>Missed report after the reporting window closes.</td><td><strong>-1 point</strong></td></tr><tr><td>Do not meet all SLA requirements.</td><td><strong>-2 points</strong></td></tr><tr><td>Performances bellow 20% of the SLA requirements.</td><td><strong>-3 points</strong></td></tr></tbody></table>

**The Reputation Score is the mean of daily scores considering all the data units**

### :chart\_with\_downwards\_trend: Decay Mechanism

To prevent older performance records from having undue influence, scores decay by **10 point per month** if no new QoS data is recorded **until reaching the score of 50 points**.

***

## :8ball: Reporting and Transparency

**Providers** can view their reputation scores in a **dashboard** that includes:

* Objective Score with detailed SLA compliance data.
* Community Notes with aggregated feedback and trends.

**Consumers can view a provider's Overall Reputation Score**, along with badges for exceptional performance (e.g., "100% SLA Compliance for 6 Months").

***

## :top: Incentives for High Reputation

* **Priority Listing**: High-reputation Providers appear at the top of Consumer search results.
* **Trust Badges**: Visible indicators of reliability (e.g., "Top Performer").

This system ensures a balanced approach to evaluating Providers and Consumers, combining hard metrics with consumer trust to create a fair and transparent ecosystem.


# Setup the Cloud and AI Gateway

This section guides you through the complete onboarding flow to configure your **Cloud and AI Gateway** in Flashgate.

You will move through three practical stages:

1. **Add Resources**: connect your storage buckets and AI providers.
2. **Build a Repository**: group those resources behind one logical endpoint with access keys.
3. **Test a Repository**: validate data and AI operations end-to-end before production use.

## What you will find in this guide

* [**Add Resources**](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage): how to register external resources (cloud storage and AI LLM connectors) in your organization.
* [**Build a Repository**](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1): how to create and configure a repository, including endpoint details and API credentials.
* [**Test a Repository**](/guides/setup-the-cloud-and-ai-gateway/test-a-repository): how to test object storage and prompt workflows through your Flashgate endpoint.

## Before you start

Make sure your account and organization are ready, and that you have access to the target cloud provider accounts you want to connect.


# Add Resources

In this step, you register the external services that Flashgate will orchestrate through the gateway.

The goal is to declare the source components first, so they can later be assembled into repositories.

## What this section covers

* [**Configure a Bucket**](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket): connect cloud storage resources (S3-compatible, GCS-compatible, or Azure Blob), including authentication and endpoint options.
* [**Configure an AI LLM**](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1): add and validate AI model providers so prompts can be routed through Flashgate.

## Expected outcome

At the end of this section, your organization has reusable **resource connectors** (storage + AI) ready to be attached to one or more repositories.


# Configure a Bucket

{% hint style="info" %}
We highly recommend to read the page describing the [Cloud Storage](/flashgate-platform/cloud-and-ai-gateway/cloud-storage) in Flashgate and you can also set up a bucket with our [API calls](/support-reference/platform-api-reference/storage-apis/bucket-management).
{% endhint %}

{% hint style="danger" %}
The guide is experimental and may contain errors as our technology continues to evolve. If you encounter any problems, please do not hesitate to contact us in [Discord](https://discord.com/invite/yy8kyM5qFB) and give us your feedback.
{% endhint %}

## Properties

Each bucket has the following properties:<br>

* **Bucket Label** (required)\
  A human-readable description of the bucket.
* **Storage Type**\
  Supported storage types according to its API interface:

  * AWS S3 or equivalent S3-compatible storage buckets indicating the custom endpoint.
  * Google Cloud Storage or equivalent GCS-compatible storage buckets indicating the custom endpoint.
  * Microsoft Azure Blob.

  Example: Connect to an S3-compatible endpoint, you will select “S3”.

## Access Mechanisms for Flashgate

There are 2 access mechanisms to the APIs:

* **Classic access**\
  Providing API key/secret (S3) or client email/private key (GCS).
* **Delegated access to** [**Flashgate platform account**](/guides/configure-external-delegated-credentials)\
  Only available if we access a native S3/GCS/Azure Blob endpoint:
  * **S3**: Require an access Role ARN (resource name) and external ID created for Flashgate AWS user, with the access policy configured for the destination bucket(s).
  * **GCS**: Flashgate service account (GCS) with token creation permission and permissions to the GCS buckets.
  * **Azure**: Flashgate Azure identity with guest/service-principal access granted through RBAC at storage account or container scope. See [Azure Blob delegated access](/guides/configure-external-delegated-credentials/configure-external-access-for-azure-blob).

{% hint style="info" %}
For general details explaining how the delegation process/grant guest access works:

* In AWS/S3, check out [this article](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html).
* In Google Cloud/GCS, check out [this article](https://cloud.google.com/iam/docs/manage-access-service-accounts).
* In Azure/Blob, check out [this article](https://learn.microsoft.com/en-us/azure/storage/blobs/assign-azure-role-data-access?tabs=portal).
  {% endhint %}

## Storage Type

{% hint style="danger" %}
All bucket and storage-account names must be globally unique across S3, GCS, and Azure—no two providers can use the same name. This is essential for a stable integration in the [Repositories](/flashgate-platform/cloud-and-ai-gateway/repositories).\
**Collisions such as an S3/GCS bucket named `mybucket` and an Azure storage account or container under `mybucket` are not allowed, though multiple containers from the&#x20;*****same*****&#x20;Azure storage account are permitted.**
{% endhint %}

### AWS S3 or Compatible Provider

You must indicate the parameters to allow access the remote bucket.

* **Bucket Name**\
  As it appears in the S3 configuration or in the URLs.
* **Access Key/ARN** (required)\
  API key or [AWS delegated Role ARN](/guides/configure-external-delegated-credentials/configure-external-access-for-aws-s3) to access the bucket.
* **Secret Key** (required)\
  API secret or [External ID](/guides/configure-external-delegated-credentials#configure-external-access-for-aws-s3) to access the bucket.
* **Endpoint** (optional)\
  An URL for the endpoint. **If empty, we assume we are connecting to AWS**. If not empty, we assume a non-AWS S3-compatible API endpoint from an external data provider.
* **Region** (required if **endpoint** field is empty)\
  AWS region the bucket is in. Not needed if we provide a custom, non-AWS endpoint.

### GCS or Compatible Provider

You must indicate the parameters to allow access the remote bucket.

* **Bucket Name**\
  As it shows in the Project storage section.
* **Client Email** (required)\
  Client email to access the bucket. It can be the service account or a [delegated service account](/guides/configure-external-delegated-credentials/configuring-external-access-for-gcss-buckets) that has been configured to grant external access to Flashgate's service account
* **Private Key** (empty if delegated access)\
  Private key to access the bucket.
* **Endpoint**\
  An URL of the endpoint. If empty, we assume we are connecting to a GCS bucket. If not empty, we assume a non-GCP GCS-compatible API endpoint from an external data provider.

### Microsoft Azure

You must indicate the parameters to allow access the remote bucket (container in Azure terms).

* **Storage Account**
* **Container**
* **Access key**: account key from Azure Storage Account (optional in delegated setups). For delegated guidance, see [Configure Azure Blob delegated access](/guides/configure-external-delegated-credentials/configure-external-access-for-azure-blob).

## Instructions

Here’s a step-by-step guide to creating a new Bucket in the Flashgate Platform:

{% stepper %}
{% step %}

#### Access the Buckets page

In the left-hand menu, select **Storage** → **Buckets**.
{% endstep %}

{% step %}

#### Create a new Connector (called Bucket)

Click the + **Add Bucket** button and select the provider where you will connect your tenant bucket or storage account to this Flashgate bucket.
{% endstep %}

{% step %}

#### Fill in the Bucket properties

On the “Create Bucket” form, enter the following fields (all are required unless noted otherwise):

**Bucket Label:** human-readable label for this bucket of the Flashgate Platform (e.g. “Backups-EU”).

{% hint style="info" %}
We recommend to have unique name per bucket to avoid issues when you'll set up [your repository](/flashgate-platform/cloud-and-ai-gateway/repositories).
{% endhint %}

**Storage Type:** You can choose of:

* **S3** (AWS or any S3-compatible endpoint provider)
* **GCS** (GCP or any GCS-compatible endpoint provider)
* **Azure Blob** (only Microsoft Azure)
  {% endstep %}

{% step %}

#### Add Vendor's Bucket

***AWS or any S3-compatible provider***

* **Bucket Name:** The exact identifier as defined by your provider in your vendor tenant (e.g. the S3 bucket name in your AWS account).
* **Access Key**: Your S3 API Key/AWS access key ID **OR** the IAM Role ARN if using [AWS delegated Role ARN](/guides/configure-external-delegated-credentials/configure-external-access-for-aws-s3)
* **Secret Key**: Your AWS secret key **OR** External ID for delegated roles
* **Endpoint** *(optional)*: custom S3 endpoint URL **OR** leave blank if using AWS
* **Region**: AWS region required if no custom endpoint.

***GCP or any GCS-compatible provider***

* **Bucket Name:** The exact identifier as defined by your provider in your vendor tenant (e.g. the S3 bucket name in your GCS account).
* **Client Email**: Your service account email **OR** a [delegated service account](/guides/configure-external-delegated-credentials/configuring-external-access-for-gcss-buckets)
* **Private Key**: service account private key **OR** leave blank if using delegated access
* **Endpoint** *(optional)*: custom GCS-compatible endpoint **OR** leave blank if using GCP

***Azure***

* **Storage Account**: your Azure storage account name
* **Container**: the container within that account
* **Access Key** *(optional)*: account key **OR** leave blank for delegated guest access
  {% endstep %}

{% step %}

#### Save your new Bucket

Click **Save** (or **Create**) at the bottom of the form. Your bucket will now appear in the list, and you can begin using it in Repositories, generate API keys, or attach it to workflows.
{% endstep %}
{% endstepper %}


# Configure an AI LLM

{% hint style="info" %}
Before following this guide, we strongly recommend reading [AI LLM](/flashgate-platform/cloud-and-ai-gateway/ai-llm) to understand how provider configurations, repositories, AI API keys, and policies work together in Flashgate. You can also review the [AI LLM Management APIs](/support-reference/platform-api-reference/ai-apis/ai-llms) if you want to automate setup.
{% endhint %}

{% hint style="danger" %}
This guide is experimental and may evolve with the platform. If something behaves differently in your workspace, please contact us on [Discord](https://discord.com/invite/yy8kyM5qFB).
{% endhint %}

## Properties

Each AI LLM configuration uses the following properties:<br>

* **Configuration Name** (required)\
  Human-readable label of the provider connection in your workspace.
* **AI LLM Type** (required)\
  Provider compatibility type used by Flashgate to route and validate calls.
* **API Endpoint** (required)\
  Base URL of the provider endpoint (for example `https://api.openai.com/v1`).
* **API Key** (optional)\
  Optional key field for providers/setups that require an additional access key.
* **API Secret** (required)\
  Main secret/token used to authenticate requests.
* **Workspace** (required, auto-selected)\
  The current workspace where the configuration is created.

## Access & security model

AI LLM credentials in Flashgate follow the same security principles used for other connected resources:

* Secrets are encrypted at rest.
* Secrets are never returned in clear text by the APIs.
* Access is scoped by workspace permissions.
* Configuration names should be unique and explicit to avoid confusion during repository setup.

{% hint style="info" %}
For the full security model (encryption/decryption behavior, scope, and best practices), see [Security and Secret Encryption](/support-reference/security-and-secret-encryption).
{% endhint %}

## AI LLM Type

When creating a configuration, select the provider type that matches your endpoint:

* **OPENAI**: OpenAI-compatible endpoints.
* **GOOGLE**: Google AI/Gemini-compatible setup.
* **ANTHROPIC**: Anthropic Claude-compatible setup.
* **AWS**: AWS AI services (e.g., Bedrock-compatible usage through your chosen endpoint/proxy).
* **OTHER**: Any custom endpoint compatible with one of the supported API patterns (commonly OpenAI-compatible on-prem/private providers).

All provider types currently use the same form fields in the UI:

* Configuration Name
* API Endpoint
* API Key (optional)
* API Secret
* Workspace (auto-defined)

## Instructions

Here is the step-by-step process to connect an AI LLM provider in Flashgate Platform.

{% stepper %}
{% step %}

#### Open AI LLM management

In the left menu, go to **AI** (or **AI → Overview**), then open **AI LLM**.\
You can start creation from either:

* the **+ / Add** action in **Overview**, or
* the **+ / Add** action in **AI LLM**.
  {% endstep %}

{% step %}

#### Start a new AI LLM configuration

Click **Add AI LLM** (or equivalent **+** action) to open the creation form.
{% endstep %}

{% step %}

#### Select the AI LLM type

Choose the provider compatibility group:

* OpenAI
* Google Cloud
* Anthropic Cloud
* AWS
* Other

Use **Other** for self-hosted/decentralized endpoints that are API-compatible with supported provider patterns.
{% endstep %}

{% step %}

#### Fill in configuration fields

Complete the form with your provider values:

* **Configuration Name**: clear unique name (example: `prod-openai-gateway`).
* **API Endpoint**: provider base URL.
* **API Key**: optional, only if your provider requires this extra key.
* **API Secret**: required provider secret/token.
* **Workspace**: already selected from your current workspace context.

{% hint style="warning" %}
Double-check endpoint protocol (`https://`), path (`/v1` when needed), and token format before saving. Most validation failures come from endpoint typos or invalid/expired secrets.
{% endhint %}
{% endstep %}

{% step %}

#### Create the configuration

Click **Create configuration**. The AI LLM resource is now attached to your workspace and appears in the AI LLM list.
{% endstep %}

{% step %}

#### (Recommended) Validate and operate safely

After creation:

1. Validate connectivity (UI/API validation flow).
2. Attach the AI LLM to a Repository when needed.
3. Rotate keys regularly and update configuration when credentials change.
4. Remove unused configurations to keep workspace governance clean.
   {% endstep %}
   {% endstepper %}

## Troubleshooting tips

* **Validation fails with authentication error**: verify API Secret (and API Key if used), then rotate credentials.
* **Provider returns endpoint/model errors**: verify endpoint base URL and provider compatibility type.
* **Configuration not visible where expected**: check current workspace and your workspace permissions.
* **Calls blocked by policy**: review applied AI Policies at organization/workspace/repository scope.


# Build a Repository

A repository is the central configuration unit that binds your connected resources into a single operational endpoint.

In this stage, you define how Flashgate exposes access to storage and AI services through repository-level credentials and policies.

## What this section covers

* [**Create a Repository**](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1/create-a-repository): create the repository, define base metadata, and generate API credentials.
* [**Configure a Repository**](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1/program-with-flashgate): attach previously created resources and fine-tune repository behavior.

## Expected outcome

After this step, you should have at least one repository that is fully configured and ready to be tested with real requests.


# Create a Repository

{% hint style="info" %}
Before creating repositories, read [Repositories](/flashgate-platform/cloud-and-ai-gateway/repositories), [Configure a Bucket](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket), and [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1).
{% endhint %}

{% hint style="danger" %}
UI labels can evolve over time. If a button/label slightly differs in your workspace, follow the same flow and contact us on [Discord](https://discord.com/invite/yy8kyM5qFB) if needed.
{% endhint %}

## What changed in the UI

The **Repositories** area is now a top-level section in **Cloud and AI Gateway** (not only a storage sub-section). It is organized into three categories:

* **Overview**: global view of repository activity and quick access to repository details.
* **Inventory**: list of all repositories; this is where you usually create repositories.
* **API Keys**: centralized list of repository API keys across repositories.

You can create a repository from **Overview** or **Inventory** using the **Add** button.

## Repository properties to define at creation time

When you create a repository, focus on these properties:

1. **Name**
   * Human-readable identifier (for example `prod-eu-data`, `assistant-ai-gateway`).
2. **API endpoint type**
   * Select the protocol your applications will use for this repository:
     * **S3**, **GCS**, or **Azure Blob** for storage resources.
     * **OpenAI** for AI LLM resources.
3. **Initial resources**
   * You can attach existing resources during creation, then add more later.
   * Supported resource families include:
     * Cloud Storage buckets/containers/accounts
     * AI LLM configurations
     * Packets (if enabled in your workspace UI)

{% hint style="danger" %}
To avoid collisions and keep the repository virtual namespace coherent, apply these rules during creation:

* **S3 & GCS storage resources**
  * Bucket names must be unique **across providers** inside the same repository.
  * You **cannot** mix an S3 bucket named `mybucket` with a GCS bucket also named `mybucket` in one repository.
* **Azure Blob storage resources**
  * Azure storage **account names** must not collide with S3/GCS bucket names in the same repository.
  * You **cannot** combine:
    * an S3 or GCS bucket called `mystorage`
    * with an Azure container under a storage account also called `mystorage` in the same repository.
  * You **may** include multiple containers from the same Azure storage account in one repository.
    {% endhint %}

{% hint style="warning" %}
Do **not** generate API keys during repository creation. API key generation belongs to repository configuration and is covered in [Configure a Repository](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1/program-with-flashgate).
{% endhint %}

## Instructions

{% stepper %}
{% step %}

### Open Repositories

Open **Cloud and AI Gateway** and go to **Repositories**.
{% endstep %}

{% step %}

### Choose where to create

Open either:

* **Overview** and click **Add or (+) button**, or
* **Inventory** and click (**+)** .
  {% endstep %}

{% step %}

### Fill repository basics

Complete the form:

* **Name**
* Optional description/labels (if available in your UI)
  {% endstep %}

{% step %}

### Attach initial resources

Use **Add resource** to attach one or more existing resources (Storage, AI LLM) with **API endpoint type** (**S3**, **GCS**, **Azure Blob**, or **OpenAI** depending on your use case).

For storage resources, keep a collision-free namespace inside the same repository:

* You cannot attach two resources that create naming conflicts in the exposed virtual namespace.
* Typical collision case: same bucket/account identifier reused across providers in one repository.

{% hint style="danger" %}
Collision reminder:

* S3 and GCS names must stay unique across providers inside the same repository.
* Azure storage account names must not overlap with S3/GCS identifiers in that repository.
  {% endhint %}
  {% endstep %}

{% step %}

### Save the repository

Click **Finish Setup**. The repository appears in **Inventory** and is visible in **Overview** (depending on the usage).
{% endstep %}
{% endstepper %}

### Continue with configuration

Open your new repository and continue with [Configure a Repository](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1/program-with-flashgate) to:

* add/remove resources,
* review endpoint and SDK details,
* generate and manage API keys.

## Related API references

If you automate repository creation/configuration:

* [Repository Management APIs](/support-reference/platform-api-reference/repo-management)
* [Bucket Management APIs](/support-reference/platform-api-reference/storage-apis/bucket-management)
* [AI LLM Management APIs](/support-reference/platform-api-reference/ai-apis/ai-llms)


# Configure a Repository

After creation, repository configuration is where you manage the repository lifecycle: resources, endpoint behavior, and API keys.

{% hint style="info" %}
You can open repository details from both **Overview** and **Inventory** in **Cloud and AI Gateway** → **Repositories**.
{% endhint %}

## What you can configure

In a repository detail page, you usually have two operational sections:

1. **Resources**
   * View currently attached resources.
   * Use **Add** to attach existing resources or create new ones from inside the repository flow (depending on enabled providers/features).
   * Supported resource families can include Cloud Storage, AI LLM, and Packets.
2. **API Keys**
   * Generate and manage repository API keys used by applications and SDKs.

## Configure resources

{% hint style="danger" %}
Resource collision rules still apply during configuration updates:

* **S3 & GCS**: bucket names must be unique across providers within one repository.
* **Azure Blob**: storage account names must not collide with S3/GCS bucket identifiers in that same repository.
* You can attach multiple Azure containers from the same storage account, as long as global repository namespace collisions are avoided.
  {% endhint %}

{% stepper %}
{% step %}

#### Open repository details

From **Overview** or **Inventory**, click a repository name/card to open its details.
{% endstep %}

{% step %}

#### Review current resources and endpoint context

In the resources area, review:

* attached resource list,
* selected API endpoint type,
* SDK/protocol context exposed by this repository.
  {% endstep %}

{% step %}

#### Add resources

Click **Add** in the resources section, then choose to attach:

* storage resources,
* AI LLM resources,
* other supported resource types in your workspace.

If needed, you may also create new resources from this flow, then attach them immediately.
{% endstep %}

{% step %}

#### Save changes and validate

Save the configuration and verify resource visibility in the repository detail page.
{% endstep %}
{% endstepper %}

## Generate and manage API keys (in configuration)

API key generation belongs to repository configuration (not repository creation).

Each repository key is scoped to the repository and to an endpoint compatibility model. A key grants access according to its access mode to the compatible resources currently attached to that repository.

You can generate repository API keys with **two valid UI paths**:

1. **Centralized path**: open **Repositories** → **API Keys** from the left menu, then add/manage keys across repositories from one page.
2. **Repository detail path**: open one repository from **Overview** or **Inventory**, scroll to the **API Keys** table in repository details, then click **Add**.

{% hint style="info" %}
Use the centralized page for fleet operations (multi-repository), and the repository detail table for contextual operations right after creating/configuring a specific repository.
{% endhint %}

### Option 1 — Generate keys from the centralized **Repositories → API Keys** page

{% stepper %}
{% step %}

#### Open the centralized API Keys page

In the left menu, open **Cloud and AI Gateway** → **Repositories** → **API Keys**.
{% endstep %}

{% step %}

#### Click Add and select repository/type

Click **Add** (or **Add API Key**) and choose:

* target **Repository**,
* key family / endpoint compatibility (**Storage** or **AI LLM** according to your use case),
* **Description**,
* **Access mode** (READ / WRITE / READ-WRITE / provider-dependent options).
  {% endstep %}

{% step %}

#### Save and copy secret immediately

Create the key, then copy the secret immediately and store it in your secret manager.
{% endstep %}
{% endstepper %}

### Option 2 — Generate keys from the repository detail **API Keys table**

{% stepper %}
{% step %}

#### Open repository details

From **Overview** or **Inventory**, open the target repository.
{% endstep %}

{% step %}

#### Find the API Keys table

In repository details, scroll to the **API Keys** table section (inside the repository detail page).
{% endstep %}

{% step %}

#### Click Add in the API Keys table

Click **Add** and create either:

* a **Storage API key** (for S3/GCS/Azure Blob-compatible repository usage), or
* an **AI LLM API key** (for OpenAI-compatible repository usage).

Then define description and access mode according to your policy.
{% endstep %}

{% step %}

#### Save and copy secret immediately

After creation, copy the generated secret and store it in your secret manager.

{% hint style="danger" %}
The full secret is displayed only once at creation time. If lost, generate a new key and rotate credentials in all clients.
{% endhint %}
{% endstep %}

{% step %}

#### Maintain keys safely

For each key, you can later:

* update description,
* adjust access mode (when allowed),
* revoke/delete the key.

Use least-privilege and periodic rotation.
{% endstep %}
{% endstepper %}

### Endpoint compatibility reminder

| Cloud Storage endpoint types | AI endpoint types              |
| ---------------------------- | ------------------------------ |
| **S3**                       | **OPENAI** (OpenAI-compatible) |
| **GCS**                      |                                |
| **AZURE BLOB**               |                                |

Key display formats can differ by endpoint type. For example, storage-oriented key IDs and secrets may be shown differently from AI-oriented credentials. Always copy and store credential values at creation time.

## Security notes

* Secrets are sensitive credentials and should be stored only in secured secret managers.
* Avoid sharing keys between teams/services; create dedicated keys per workload.
* Rotate and revoke keys during incident response or role changes.
* See [Security and Secret Encryption](/support-reference/security-and-secret-encryption) for platform-level handling principles.

{% hint style="danger" %}
You cannot recover a previously displayed repository API secret from the UI after creation. Plan credential rotation workflows in advance and document ownership for every key.
{% endhint %}

## Related API references

* [Repo API Keys (Storage)](/support-reference/platform-api-reference/storage-apis/api_keys)
* [AI API Keys](/support-reference/platform-api-reference/ai-apis/ai-api-keys)
* [Repository Management APIs](/support-reference/platform-api-reference/repo-management)


# Test a Repository

This section validates that your repository works correctly from client applications.

You will run practical checks against your Flashgate endpoint to confirm credentials, routing, and provider integration.

## What this section covers

* [**Store An Object**](/guides/setup-the-cloud-and-ai-gateway/test-a-repository/program-with-flashgate): test write/read behavior for cloud storage resources configured in your repository.
* [**Send a Prompt**](/guides/setup-the-cloud-and-ai-gateway/test-a-repository/program-with-flashgate-1): test AI prompt routing and response flow through the configured LLM provider.

## Expected outcome

By the end, you should be able to perform both storage and AI operations successfully using repository API keys, giving you confidence before moving to production traffic.


# Store An Object

{% hint style="danger" %}
The guide is experimental and may contain errors as our technology continues to evolve. If you encounter any problems, please do not hesitate to contact us in [Discord](https://discord.com/invite/yy8kyM5qFB) and give us your feedback.
{% endhint %}

This guide demonstrates how to interact with the Flashgate Platform to upload and download files in your application backend:

* [AWS S3](#aws-s3-via-boto3)
* [GCS](#google-cloud-storage-via-google-cloud-storage)
* [Azure Blob](#azure-blob-storage-via-azure-storage-blob)

## Prerequisites

{% tabs %}
{% tab title="Python" %}

* **Python 3.9+**
* A Flashgate Repository with a valid API key (READ or WRITE) – see [Create a Repository](https://chatgpt.com/g/g-p-6835f9a52acc8191af6b6fcc83a2c587-flashgate-docs/c/68386637-d934-8002-9201-ab16f5c347ea?model=o4-mini-high#create-a-repository).
* Network access to your Bridge endpoints.

**Install Required Packages**

```bash
pip install boto3 google-cloud-storage azure-storage-blob
```

{% endtab %}

{% tab title="Javascript" %}

* **Node.js v14+**
* A Flashgate Repository with a valid API key (READ or WRITE) – see [Create a Repository](https://chatgpt.com/g/g-p-6835f9a52acc8191af6b6fcc83a2c587-flashgate-docs/c/68386637-d934-8002-9201-ab16f5c347ea?model=o4-mini-high#create-a-repository).
* Network access to your Bridge endpoints

**Install Required Packages**

```bash
npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner \
            @google-cloud/storage \
            @azure/storage-blob
```

{% endtab %}

{% tab title="Go" %}

* **Go 1.18 or later**
* A Flashgate Repository with a valid API key (READ or WRITE) — see [Create a Repository](https://chatgpt.com/g/g-p-6835f9a52acc8191af6b6fcc83a2c587-flashgate-docs/c/68386637-d934-8002-9201-ab16f5c347ea?model=o4-mini-high#create-a-repository).
* Network access to your Flashgate Bridge endpoints

Install required packages:

```bash
go get github.com/aws/aws-sdk-go-v2@latest
go get github.com/aws/aws-sdk-go-v2/config
go get cloud.google.com/go/storage
go get github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
```

{% endtab %}
{% endtabs %}

***

## AWS S3

{% stepper %}
{% step %}

### Configuration

Set up the S3 client with your Flashgate endpoint and credentials:

{% tabs %}
{% tab title="Python" %}

```python
# flashgate_aws_config.py
import boto3
from botocore.client import Config

# Replace with your Flashgate credentials and endpoint
ENDPOINT = "https://s3-us-east-1-aws.flashback.tech"
# Consider READ/WRITE API Information of the Repository
API_KEY_ID = "YOUR_API_KEY_ID"
API_SECRET = "YOUR_API_SECRET"

session = boto3.session.Session(
    aws_access_key_id=API_KEY_ID,
    aws_secret_access_key=API_SECRET
)

s3_client = session.client(
    service_name="s3",
    endpoint_url=ENDPOINT,
    config=Config(signature_version="s3v4")
)
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
// flashgateAwsConfig.js
import { S3Client } from "@aws-sdk/client-s3";

// Replace with your Flashgate credentials and endpoint
const ENDPOINT   = "https://s3-us-east-1-aws.flashback.tech";
const API_KEY_ID = "YOUR_API_KEY_ID";
const API_SECRET = "YOUR_API_SECRET";

export const s3Client = new S3Client({
  endpoint: ENDPOINT,
  region:   "us-east-1",
  credentials: {
    accessKeyId:     API_KEY_ID,
    secretAccessKey: API_SECRET
  },
  forcePathStyle: true
});
```

{% endtab %}

{% tab title="Go" %}

```go
// flashgate_aws_config.go
package flashgate

import (
  "context"
  "github.com/aws/aws-sdk-go-v2/aws"
  "github.com/aws/aws-sdk-go-v2/config"
  "github.com/aws/aws-sdk-go-v2/credentials"
  "github.com/aws/aws-sdk-go-v2/service/s3"
  s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
)

func NewS3Client() (*s3.Client, error) {
  // Replace with your Flashgate endpoint and credentials
  endpoint   := "https://s3-us-east-1-aws.flashback.tech"
  apiKey     := "YOUR_API_KEY_ID"
  apiSecret  := "YOUR_API_SECRET"

  // Load default config and override credentials and endpoint
  cfg, err := config.LoadDefaultConfig(context.TODO(),
    config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(apiKey, apiSecret, "")),
    config.WithEndpointResolverWithOptions(aws.EndpointResolverWithOptionsFunc(
      func(service, region string, opts ...interface{}) (aws.Endpoint, error) {
        if service == s3.ServiceID {
          return aws.Endpoint{
            URL:           endpoint,
            SigningRegion: "us-east-1",
          }, nil
        }
        return aws.Endpoint{}, &aws.EndpointNotFoundError{}
      })),
  )
  if err != nil {
    return nil, err
  }

  return s3.NewFromConfig(cfg, func(o *s3.Options) {
    o.UsePathStyle = true
  }), nil
}
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Upload a File

Upload a local file to your specified bucket:

{% tabs %}
{% tab title="Python" %}

<pre class="language-python"><code class="lang-python"># aws_upload.py
from flashgate_aws_config import s3_client

<strong>#S3 Bucket, GCS Bucket, or Azure Container listed in your Repository
</strong>BUCKET_NAME = "your-bucket-name"
FILE_PATH = "path/to/local/file.txt"
OBJECT_NAME = FILE_PATH.split("/")[-1]

s3_client.upload_file(
    Filename=FILE_PATH,
    Bucket=BUCKET_NAME,
    Key=OBJECT_NAME
)
print(f"Uploaded {OBJECT_NAME} to {BUCKET_NAME}")
</code></pre>

{% endtab %}

{% tab title="Javascript" %}

```javascript
// awsUpload.js
import { PutObjectCommand } from "@aws-sdk/client-s3";
import fs                  from "fs";
import { s3Client }        from "./flashgateAwsConfig.js";

const BUCKET_NAME = "your-bucket-name";
const FILE_PATH   = "path/to/local/file.txt";
const OBJECT_NAME = FILE_PATH.split("/").pop();
const BODY        = fs.readFileSync(FILE_PATH);

(async () => {
  await s3Client.send(new PutObjectCommand({
    Bucket: BUCKET_NAME,
    Key:    OBJECT_NAME,
    Body
  }));
  console.log(`Uploaded ${OBJECT_NAME} to ${BUCKET_NAME}`);
})();
```

{% endtab %}

{% tab title="Go" %}

```go
// aws_upload.go
package main

import (
  "context"
  "fmt"
  "flashgate"
  "os"
)

func main() {
  client, err := flashgate.NewS3Client()
  if err != nil {
    panic(err)
  }

  bucket := "your-bucket-name"
  key    := "file.txt"
  file, err := os.Open("path/to/local/file.txt")
  if err != nil {
    panic(err)
  }
  defer file.Close()

  _, err = client.PutObject(context.TODO(), &s3.PutObjectInput{
    Bucket: aws.String(bucket),
    Key:    aws.String(key),
    Body:   file,
  })
  if err != nil {
    panic(err)
  }

  fmt.Printf("Uploaded %s to %s\n", key, bucket)
}
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Download a File

Download an object from your repository to a local path:

{% tabs %}
{% tab title="Python" %}

```python
# aws_download.py
from flashgate_aws_config import s3_client

#S3 Bucket, GCS Bucket, or Azure Container listed in your Repository
BUCKET_NAME = "your-bucket-name"
OBJECT_NAME = "file.txt"
DEST_PATH = "downloads/file.txt"

s3_client.download_file(
    Bucket=BUCKET_NAME,
    Key=OBJECT_NAME,
    Filename=DEST_PATH
)
print(f"Downloaded {OBJECT_NAME} to {DEST_PATH}")
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
// awsDownload.js
import { GetObjectCommand } from "@aws-sdk/client-s3";
import fs                  from "fs";
import { s3Client }        from "./flashgateAwsConfig.js";

const BUCKET_NAME = "your-bucket-name";
const OBJECT_NAME = "file.txt";
const DEST_PATH   = "downloads/file.txt";

(async () => {
  const { Body } = await s3Client.send(new GetObjectCommand({
    Bucket: BUCKET_NAME,
    Key:    OBJECT_NAME
  }));
  const chunks = [];
  for await (let chunk of Body) chunks.push(chunk);
  fs.writeFileSync(DEST_PATH, Buffer.concat(chunks));
  console.log(`Downloaded ${OBJECT_NAME} to ${DEST_PATH}`);
})();
```

{% endtab %}

{% tab title="Go" %}

```go
// aws_download.go
package main

import (
  "context"
  "fmt"
  "flashgate"
  "io"
  "os"
)

func main() {
  client, err := flashgate.NewS3Client()
  if err != nil {
    panic(err)
  }

  bucket   := "your-bucket-name"
  key      := "file.txt"
  destPath := "downloads/file.txt"

  resp, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
    Bucket: aws.String(bucket),
    Key:    aws.String(key),
  })
  if err != nil {
    panic(err)
  }
  defer resp.Body.Close()

  outFile, err := os.Create(destPath)
  if err != nil {
    panic(err)
  }
  defer outFile.Close()

  if _, err = io.Copy(outFile, resp.Body); err != nil {
    panic(err)
  }

  fmt.Printf("Downloaded %s to %s\n", key, destPath)
}
```

5.

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

***

## Google Cloud Storage

{% stepper %}
{% step %}

### Configuration

Initialize a GCS client pointing to your Flashgate Bridge endpoint:

{% tabs %}
{% tab title="Python" %}

```python
# flashgate_gcs_config.py
from google.cloud import storage
from google.oauth2 import service_account

# Replace with your Flashgate credentials and endpoint
ENDPOINT = "https://s3-us-east-1.aws.flashback.tech"
# Consider READ/WRITE API Information of the Repository
CLIENT_EMAIL = "YOUR_CLIENT_EMAIL"
PRIVATE_KEY = "YOUR_PRIVATE_KEY"

credentials = service_account.Credentials.from_service_account_info({
    "type": "service_account",
    "client_email": CLIENT_EMAIL,
    "private_key": PRIVATE_KEY,
})

client = storage.Client(
    credentials=credentials,
    client_options={"api_endpoint": ENDPOINT}
)
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
// flashgateGcsConfig.js
import { Storage } from '@google-cloud/storage';

// Replace with your Flashgate credentials and endpoint
const ENDPOINT     = 'https://s3-us-east-1.aws.flashback.tech';
const CLIENT_EMAIL = 'YOUR_CLIENT_EMAIL';
const PRIVATE_KEY  = 'YOUR_PRIVATE_KEY';

// Initialize client
const storage = new Storage({
  credentials: {
    client_email: CLIENT_EMAIL,
    private_key: PRIVATE_KEY.replace(/\\n/g, '\n'),
  },
  apiEndpoint: ENDPOINT.replace(/^https?:\/\//, ''),
});

export default storage;
)
```

{% endtab %}

{% tab title="Go" %}

```go
// flashgate_gcs_config.go
package flashgate

import (
  "context"
  "fmt"
  "cloud.google.com/go/storage"
  "google.golang.org/api/option"
)

const (
  // Replace with your Flashgate Bridge endpoint and service account info
  ENDPOINT     = "https://s3-us-east-1.aws.flashback.tech"
  CLIENT_EMAIL = "YOUR_CLIENT_EMAIL"
  PRIVATE_KEY  = `-----BEGIN PRIVATE KEY-----
YOUR_PRIVATE_KEY_CONTENT
-----END PRIVATE KEY-----`
  // The GCP project ID associated with your Flashgate repository
  PROJECT_ID   = "your-gcp-project-id"
)

func NewGCSClient() (*storage.Client, string, error) {
  ctx := context.Background()
  credsJSON := []byte(fmt.Sprintf(
    `{"type":"service_account","client_email":"%s","private_key":"%s"}`,
    CLIENT_EMAIL, PRIVATE_KEY,
  ))
  client, err := storage.NewClient(ctx,
    option.WithCredentialsJSON(credsJSON),
    option.WithEndpoint(ENDPOINT),
  )
  if err != nil {
    return nil, "", err
  }
  return client, PROJECT_ID, nil
}
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Upload a File as a Blob

Upload a blob to the specified GCS bucket:

{% tabs %}
{% tab title="Python" %}

```python
# gcs_upload.py
from flashgate_gcs_config import client

#S3 Bucket, GCS Bucket, or Azure Container listed in your Repository
BUCKET_NAME = "your-flashgate-bucket-name"
FILE_PATH = "path/to/local/file.txt"
OBJECT_NAME = FILE_PATH.split("/")[-1]

bucket = client.bucket(BUCKET_NAME)
blob = bucket.blob(OBJECT_NAME)
blob.upload_from_filename(FILE_PATH)
print(f"Uploaded {OBJECT_NAME} to {BUCKET_NAME}")
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
// gcsUpload.js
import storage from './flashgateGcsConfig.js';

const BUCKET_NAME = 'your-flashgate-bucket-name';
const FILE_PATH   = 'path/to/local/file.txt';
const OBJECT_NAME = FILE_PATH.split('/').pop();

(async () => {
  const bucket = storage.bucket(BUCKET_NAME);
  await bucket.upload(FILE_PATH, { destination: OBJECT_NAME });
  console.log(`Uploaded ${OBJECT_NAME} to ${BUCKET_NAME}`);
})();
```

{% endtab %}

{% tab title="Go" %}

```go
// gcs_upload.go
package main

import (
  "context"
  "fmt"
  "flashgate"
  "io"
  "os"
)

func main() {
  client, _, err := flashgate.NewGCSClient()
  if err != nil {
    panic(err)
  }
  ctx := context.Background()
  bucketName := "your-flashgate-bucket-name"
  filePath   := "path/to/local/file.txt"
  objectName := "file.txt"

  bucket := client.Bucket(bucketName)
  writer := bucket.Object(objectName).NewWriter(ctx)
  f, err := os.Open(filePath)
  if err != nil {
    panic(err)
  }
  defer f.Close()
  if _, err = io.Copy(writer, f); err != nil {
    panic(err)
  }
  if err := writer.Close(); err != nil {
    panic(err)
  }
  fmt.Printf("Uploaded %s to %s\n", objectName, bucketName)
}
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Download a File as a Blob

Download a blob from your repository:

{% tabs %}
{% tab title="Python" %}

```python
# gcs_download.py
from flashgate_gcs_config import client

#S3 Bucket, GCS Bucket, or Azure Container listed in your Repository
BUCKET_NAME = "your-bucket-name"
OBJECT_NAME = "file.txt"
DEST_PATH = "downloads/file.txt"

bucket = client.bucket(BUCKET_NAME)
blob = bucket.blob(OBJECT_NAME)
blob.download_to_filename(DEST_PATH)
print(f"Downloaded {OBJECT_NAME} to {DEST_PATH}")
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
// gcsDownload.js
import storage from './flashgateGcsConfig.js';

const BUCKET_NAME = 'your-bucket-name';
const OBJECT_NAME = 'file.txt';
const DEST_PATH   = 'downloads/file.txt';

(async () => {
  const bucket = storage.bucket(BUCKET_NAME);
  const blob = bucket.file(OBJECT_NAME);
  await blob.download({ destination: DEST_PATH });
  console.log(`Downloaded ${OBJECT_NAME} to ${DEST_PATH}`);
})();
```

{% endtab %}

{% tab title="Go" %}

```go
// gcs_download.go
package main

import (
  "context"
  "fmt"
  "flashgate"
  "io"
  "os"
)

func main() {
  client, _, err := flashgate.NewGCSClient()
  if err != nil {
    panic(err)
  }
  ctx := context.Background()
  bucketName := "your-bucket-name"
  objectName := "file.txt"
  destPath   := "downloads/file.txt"

  reader, err := client.Bucket(bucketName).Object(objectName).NewReader(ctx)
  if err != nil {
    panic(err)
  }
  defer reader.Close()
  f, err := os.Create(destPath)
  if err != nil {
    panic(err)
  }
  defer f.Close()
  if _, err = io.Copy(f, reader); err != nil {
    panic(err)
  }
  fmt.Printf("Downloaded %s to %s\n", objectName, destPath)
}
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

***

## Azure Blob Storage

{% stepper %}
{% step %}

### Configuration

Create an Azure BlobServiceClient using your Flashgate endpoint:

{% tabs %}
{% tab title="Python" %}

```python
# flashgate_azure_config.py
from azure.storage.blob import BlobServiceClient

# Replace with your Flashgate endpoint and credentials
ENDPOINT = "https://s3-us-east-1.aws.flashback.tech"
# Consider READ/WRITE API Information of the Repository
CREDENTIAL = "YOUR_CREDENTIAL"

client = BlobServiceClient(
    account_url=ENDPOINT,
    credential=CREDENTIAL
)
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
// flashgateAzureConfig.js
import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob";

// Replace with your Flashgate endpoint and credential
const ENDPOINT   = "https://s3-us-east-1.aws.flashback.tech";
const ACCOUNT    = "YOUR_ACCOUNT_NAME";
const ACCOUNT_KEY= "YOUR_ACCOUNT_KEY";

const credential = new StorageSharedKeyCredential(ACCOUNT, ACCOUNT_KEY);
export const blobServiceClient = new BlobServiceClient(ENDPOINT, credential);
```

{% endtab %}

{% tab title="Go" %}

```go
// flashgate_azure_config.go
package flashgate

import (
  "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
)

// Replace with your Flashgate endpoint and credentials
const (
  ENDPOINT     = "https://s3-us-east-1.aws.flashback.tech"
  ACCOUNT_NAME = "YOUR_ACCOUNT_NAME"
  ACCOUNT_KEY  = "YOUR_ACCOUNT_KEY"
)

// NewBlobServiceClient returns an authenticated ServiceClient
func NewBlobServiceClient() (*azblob.ServiceClient, error) {
  cred, err := azblob.NewSharedKeyCredential(ACCOUNT_NAME, ACCOUNT_KEY)
  if err != nil {
    return nil, err
  }
  return azblob.NewServiceClientWithSharedKey(ENDPOINT, cred, nil)
}
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Upload a File as a Blob

Upload a local file as a blob to your bucket:

{% tabs %}
{% tab title="Python" %}

```python
# azure_upload.py
from flashgate_azure_config import client

#S3 Bucket, GCS Bucket, or Azure Container listed in your Repository
CONTAINER_NAME = "your-bucket_name"
FILE_PATH = "path/to/local/file.txt"
BLOB_NAME = FILE_PATH.split("/")[-1]

blob_client = client.get_blob_client(container=CONTAINER_NAME, blob=BLOB_NAME)
with open(FILE_PATH, "rb") as data:
    blob_client.upload_blob(data)
print(f"Uploaded {BLOB_NAME} to {CONTAINER_NAME}")
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
// azureUpload.js
import { blobServiceClient } from "./flashgateAzureConfig.js";
import fs                     from "fs";

const CONTAINER_NAME = "your-bucket-name";
const FILE_PATH      = "path/to/local/file.txt";
const BLOB_NAME      = FILE_PATH.split("/").pop();

(async () => {
  const containerClient = blobServiceClient.getContainerClient(CONTAINER_NAME);
  const blockBlobClient = containerClient.getBlockBlobClient(BLOB_NAME);
  await blockBlobClient.uploadFile(FILE_PATH);
  console.log(`Uploaded ${BLOB_NAME} to ${CONTAINER_NAME}`);
})();
```

{% endtab %}

{% tab title="Go" %}

```go
// azure_upload.go
package main

import (
  "context"
  "fmt"
  "flashgate"
  "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
)

func main() {
  client, err := flashgate.NewBlobServiceClient()
  if err != nil {
    panic(err)
  }
  containerName := "your-bucket-name"
  blobName      := "file.txt"
  localPath     := "path/to/local/file.txt"

  containerClient := client.NewContainerClient(containerName)
  blobClient := containerClient.NewBlockBlobClient(blobName)

  resp, err := blobClient.UploadFile(context.Background(), localPath, nil)
  if err != nil {
    panic(err)
  }
  fmt.Printf("Uploaded %s to %s (request ID: %s)\n", blobName, containerName, *resp.RequestID)
}
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Download a File as a Blob

Download a blob from your container to a local path:

{% tabs %}
{% tab title="Python" %}

```python
# azure_download.py
from flashgate_azure_config import client

#S3 Bucket, GCS Bucket, or Azure Container listed in your Repository
CONTAINER_NAME = "your-flashgate-bucket_name"
BLOB_NAME = "file.txt"
DEST_PATH = "downloads/file.txt"

blob_client = client.get_blob_client(container=CONTAINER_NAME, blob=BLOB_NAME)
with open(DEST_PATH, "wb") as file:
    data = blob_client.download_blob()
    file.write(data.readall())
print(f"Downloaded {BLOB_NAME} to {DEST_PATH}")
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
// azureDownload.js
import { blobServiceClient } from "./flashgateAzureConfig.js";
import fs                     from "fs";

const CONTAINER_NAME = "your-flashgate-bucket-name";
const BLOB_NAME      = "file.txt";
const DEST_PATH      = "downloads/file.txt";

(async () => {
  const containerClient = blobServiceClient.getContainerClient(CONTAINER_NAME);
  const blockBlobClient = containerClient.getBlockBlobClient(BLOB_NAME);
  await blockBlobClient.downloadToFile(DEST_PATH);
  console.log(`Downloaded ${BLOB_NAME} to ${DEST_PATH}`);
})();
```

{% endtab %}

{% tab title="Go" %}

```go
// azure_download.go
package main

import (
  "context"
  "fmt"
  "io"
  "os"
  "flashgate"
)

func main() {
  client, err := flashgate.NewBlobServiceClient()
  if err != nil {
    panic(err)
  }
  containerName := "your-flashgate-bucket-name"
  blobName      := "file.txt"
  destPath      := "downloads/file.txt"

  containerClient := client.NewContainerClient(containerName)
  blobClient := containerClient.NewBlockBlobClient(blobName)

  downloadResp, err := blobClient.DownloadStream(context.Background(), nil)
  if err != nil {
    panic(err)
  }
  defer downloadResp.Body.Close()

  outFile, err := os.Create(destPath)
  if err != nil {
    panic(err)
  }
  defer outFile.Close()

  if _, err = io.Copy(outFile, downloadResp.Body); err != nil {
    panic(err)
  }
  fmt.Printf("Downloaded %s to %s\n", blobName, destPath)
}
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

***

## Next Steps

* Explore additional [storage API operations](https://github.com/flashbacknetwork/flashback-usermanual/blob/main/support-reference/storage-api-operations/README.md): delete, copy, multipart uploads, etc.
* Integrate and modify these snippets into your applications.


# Send a Prompt

Use this guide to validate AI/LLM integration through the **Cloud and AI Gateway** after configuring your repository.

Unlike storage tests, AI tests use the repository's **OpenAI-compatible endpoint type** and an **AI LLM API key** generated for that repository.

{% hint style="info" %}
This is the AI equivalent of **Store An Object**: you confirm connectivity, authentication, routing, and response behavior before shipping production traffic.
{% endhint %}

## Prerequisites

Before running examples, make sure all of the following are complete:

1. At least one AI provider is configured in **AI → AI LLM**.
2. The AI resource is attached to your repository.
3. The repository endpoint type is **OPENAI**.
4. You created a repository **AI LLM API key**.

Related setup guides:

* [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1)
* [Create a Repository](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1/create-a-repository)
* [Configure a Repository](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1/program-with-flashgate)

## Required endpoint and credentials

From your repository details, collect:

* **OpenAI-compatible base URL** (example: `https://openai-us-east-1-aws.flashback.tech/v1`)
* **AI API key** (Bearer token format)
* **Model identifier** available in your configured provider(s)

Then export them as environment variables:

```bash
export FB_OPENAI_BASE_URL="https://openai-us-east-1-aws.flashback.tech/v1"
export FB_OPENAI_API_KEY="YOUR_AI_API_KEY"
export FB_MODEL="gpt-4o-mini"
```

***

## Quick connectivity check (cURL)

Run a simple chat completion request through Flashgate:

```bash
curl -sS "$FB_OPENAI_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $FB_OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "'"$FB_MODEL"'",
    "messages": [
      {"role": "system", "content": "You are a concise assistant."},
      {"role": "user", "content": "Explain in one sentence what Flashgate Gateway does."}
    ],
    "temperature": 0.2
  }'
```

If successful, you should receive a JSON response containing `choices[0].message.content`.

***

## Python example

Install dependency:

```bash
pip install openai
```

```python
# send_prompt.py
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["FB_OPENAI_API_KEY"],
    base_url=os.environ["FB_OPENAI_BASE_URL"],
)

response = client.chat.completions.create(
    model=os.environ.get("FB_MODEL", "gpt-4o-mini"),
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "List 3 benefits of using an API gateway for AI workloads."}
    ],
    temperature=0.3,
)

print(response.choices[0].message.content)
```

Run:

```bash
python send_prompt.py
```

## JavaScript example

Install dependency:

```bash
npm install openai
```

```javascript
// sendPrompt.mjs
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.FB_OPENAI_API_KEY,
  baseURL: process.env.FB_OPENAI_BASE_URL,
});

const response = await client.chat.completions.create({
  model: process.env.FB_MODEL || "gpt-4o-mini",
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "Give me 3 best practices for AI key rotation." }
  ],
  temperature: 0.3,
});

console.log(response.choices[0].message.content);
```

Run:

```bash
node sendPrompt.mjs
```

## Gateway integration validation checklist

When the call succeeds, validate these integration points:

* Authentication works with the repository-level **AI LLM API key**.
* The request is routed through your Flashgate Gateway endpoint (not directly to provider).
* The selected `model` is authorized and available in your provider configuration.
* The same app code can keep a stable OpenAI-compatible contract while backend provider/policy evolves in Flashgate.

## Common errors and fixes

* **401 Unauthorized / 403 Forbidden**
  * Verify you are using an AI key (not a storage key).
  * Check key status and access mode in repository API keys.
* **404 Not Found**
  * Confirm `FB_OPENAI_BASE_URL` includes `/v1`.
  * Ensure repository endpoint type is OPENAI.
* **400 model not found / invalid model**
  * Use a model exposed by your configured provider(s).
  * Recheck provider mapping/policies in AI LLM configuration.
* **Timeout / network issues**
  * Validate DNS/network access to your Flashgate endpoint.
  * Confirm bridge node health and connectivity.

## Next steps

After this test succeeds, you can:

* implement fallback and reliability patterns for multi-provider AI routing,
* apply governance/policy controls,
* move to production with key rotation and observability.

Explore practical patterns in [AI LLM Use Cases](/guides/explore-use-cases/ai-llm).


# Deploy Your Private Node

This section covers the complete process for setting up a private Flashgate node on your own infrastructure. A private node allows you to run Flashgate's multi-cloud storage services on your own VPS, giving you full control over your data and infrastructure.

## Setup Process Overview

The private node setup involves two main phases:

1. **Prerequisites** - Prepare your infrastructure, DNS, SSL certificates, and required files
2. **Installation** - Run the automated installation script to deploy and configure the node

## What You'll Get

After successful setup, your private node will provide:

* **S3-compatible API** endpoint for AWS S3 operations
* **GCS-compatible API** endpoint for Google Cloud Storage operations
* **Azure Blob-compatible API** endpoint for Azure Blob Storage operations
* **Nginx reverse proxy** with SSL termination and load balancing
* **Docker-based services** for easy management and updates

## Next Steps

1. Review the [prerequisites](/guides/private-node-setup/prerequisites) to ensure your infrastructure is ready
2. Follow the [installation guide](/guides/private-node-setup/install-via-script) to deploy your node


# Prerequisites for Install

SSLYou are preparing a **server** (a VPS) so it can run a **Flashgate Private Node**.

This Private Node will:

* Expose **S3 / GCS / Azure Blob–style endpoints** on *your* domain
* Use **HTTPS (SSL certificates)** so traffic is secure
* Use a **Private Node key** so Flashgate knows it’s your node
* Be installed via a simple **shell script** (`rollout_node.sh`)

Think of this whole guide as: *“Get a small server, point your domain to it, give it certificates and keys, then run the installer script.”*

Here are the steps:

* [Run Your VPS](#step-1-run-your-virtual-private-server)
* [DNS Configuration](#dns-configuration)
* [SSL Certificates](#ssl-certificates)
* [Private Node Key](#private-node-key)
* [Installation Script](#installation-script)
* [Sanity Check](#sanity-check)

***

{% stepper %}
{% step %}

## Run Your VPS

#### What is a VPS?

A **VPS** (Virtual Private Server) is just a rented Linux machine in the cloud (from OVH, Hetzner, AWS, GCP, Scaleway, DigitalOcean, etc.). You connect to it with SSH and install software.

#### What you need

* **Minimum hardware**
  * **CPU:** 2 vCPU (2 virtual cores)
  * **RAM:** 2–4 GB RAM
  * **Disk:** anything reasonable (e.g. 20–40 GB) is usually enough for the node itself
* **Operating System**
  * Use **Ubuntu 22.04** or **Ubuntu 24.04** (LTS versions; most providers offer them)
* **Scalability**
  * If you expect a lot of traffic later, pick a plan that you can **upgrade** (more CPU/RAM) without rebuilding everything.

#### Action checklist

1. Pick a VPS provider.
2. Create a new server with:
   * Ubuntu 22.04 or 24.04
   * 2 vCPU, 2–4 GB RAM
3. Make sure you can SSH into it (you’ll need this later).
   {% endstep %}

{% step %}

## DNS Configuration

#### What is Domain Name System (DNS) in this context?

**DNS records** are how you say:

> “When someone goes to `s3-eu.mydomain.com` in a browser or via an SDK, send them to my VPS IP address.”

You will create several **subdomains** for different storage protocols:

* One set for **S3-compatible** APIs
* One for **Google Cloud Storage (GCS)**-style APIs
* One for **Azure Blob**–style APIs

You’ll do this in your **domain registrar** or **DNS provider** (e.g., Cloudflare, Route 53, OVH, Gandi).

#### Records you need

> Replace `<region>` and `mydomain.com` with your real values, e.g. `eu` and `storage.acme.com`.

**For S3-compatible endpoints (2 DNS records)**

* `s3-<region>.mydomain.com`\
  → main S3 endpoint (e.g. what SDKs talk to)
* `*.s3-<region>.mydomain.com`\
  → wildcard, so each bucket can be a subdomain (like `mybucket.s3-eu.mydomain.com`)

**For Google Cloud Storage (1 DNS record)**

* `gcs-<region>.mydomain.com`\
  → endpoint for GCS-style access

**For Azure Blob Storage (2 DNS records)**

* `blob-<region>.mydomain.com`\
  → main Blob endpoint
* `*.blob-<region>.mydomain.com`\
  → wildcard, so each storage account/container can be a subdomain

#### What type of DNS record?

Most of the time, you will create **A records** pointing to your VPS’s IP address, for example:

* `s3-eu.mydomain.com → 203.0.113.10` (your VPS IP)
* `*.s3-eu.mydomain.com → 203.0.113.10`
* etc.

#### Action checklist

1. Log in to your DNS provider.
2. Create **A records** for:
   * `s3-<region>.mydomain.com`
   * `*.s3-<region>.mydomain.com`
   * `gcs-<region>.mydomain.com`
   * `blob-<region>.mydomain.com`
   * `*.blob-<region>.mydomain.com`
3. Point all of them to your VPS IP address.
   {% endstep %}

{% step %}

## SSL Certificates

#### What is an Secure Sockets Layer (SSL) certificate here?

SSL/TLS certificates let your endpoints work over **https\://** instead of **http\://** and avoid browser/SDK security warnings. They prove that `s3-eu.mydomain.com` really belongs to your domain.

You can get certificates from:

* Let’s Encrypt (free, automated)
* Your DNS provider or hosting provider
* Commercial CAs like DigiCert, GlobalSign, etc.

#### Which hostnames must be covered?

For each protocol, your certificate(s) must cover specific domain names:

* **S3**
  * `s3-<region>.mydomain.com`
  * `*.s3-<region>.mydomain.com` (wildcard)
* **GCS**
  * `gcs-<region>.mydomain.com`
* **Blob**
  * `blob-<region>.mydomain.com`
  * `*.blob-<region>.mydomain.com` (wildcard)

You can:

* Use **one certificate per domain**, or
* Use **wildcard certificates** if your CA supports them.

#### Supported file formats

The Private Node supports two common formats:

1. **Separate files**
   * `.crt` → certificate
   * `.key` → private key
2. **Bundled file**
   * `.pfx` or `.p12` → certificate + private key together (often used on Windows/enterprise PKI)

#### Where to put the files?

All certificate files should be copied to the **VPS home directory** (usually `/home/ubuntu` or `/root` depending on your user).

#### Action checklist

1. Get SSL certificates for:
   * `s3-<region>.mydomain.com` and `*.s3-<region>.mydomain.com`
   * `gcs-<region>.mydomain.com`
   * `blob-<region>.mydomain.com` and `*.blob-<region>.mydomain.com`
2. On your computer, download those certificates from your CA or provider.
3. Use `scp` or your provider’s file manager to copy them to your VPS home directory.
   {% endstep %}

{% step %}

## Private Node Key

#### What is the Private Node key?

This is a **secret key file** (`private_key.pem`) that tells Flashgate:

> “This node belongs to this specific account/project.”

Without it, the platform can’t authenticate or manage your node.

#### What you need to do

1. **In the Flashgate platform UI:**
   * Go to wherever Private Nodes are managed.
   * Click to **create/generate a Private Node key**.
2. Download the `private_key.pem` file.
3. Copy `private_key.pem` to the VPS **home directory**, next to your certificates.

#### Action checklist

1. Generate the node key in Flashgate.
2. Download `private_key.pem`.
3. Copy `private_key.pem` to `~/` on your VPS.
   {% endstep %}

{% step %}

## Installation Script

#### What is the script?

`rollout_node.sh` is a shell script that:

* Installs all required packages
* Configures the node
* Reads your certificates + `private_key.pem`
* Sets up the services

You will simply **run this script** instead of typing all commands manually.

#### What you need to do

1. **Download the script on the VPS**\
   From your VPS (over SSH), run something like:

   ```bash
   cd ~
   curl -O https://github.com/<your-org-or-repo>/rollout_node.sh
   ```

   > (Use the real GitHub URL from your docs or repo.)
2. **Make it executable**

   ```bash
   chmod +x rollout_node.sh
   ```
3. Follow the detailed steps in `install-via-script.md`
   * That file will tell you *exactly* how to run the script, with which options.

#### Action checklist

1. SSH into the VPS.
2. Download `rollout_node.sh` into the home directory.
3. Run `chmod +x rollout_node.sh`.
4. Keep `install-via-script.md` open while you run the script.
   {% endstep %}

{% step %}

## Sanity Check

When you’re done with all prerequisites, your home directory (`~`) should look like one of the following.

#### Option A – Using separate `.crt` + `.key` files

```
~/s3-<region>.mydomain.com.crt
~/s3-<region>.mydomain.com.key

~/gcs-<region>.mydomain.com.crt
~/gcs-<region>.mydomain.com.key

~/blob-<region>.mydomain.com.crt
~/blob-<region>.mydomain.com.key

~/private_key.pem
~/rollout_node.sh
```

#### Option B – Using `.pfx` certificates

```
~/s3-<region>.mydomain.com.pfx
~/gcs-<region>.mydomain.com.pfx
~/blob-<region>.mydomain.com.pfx

~/private_key.pem
~/rollout_node.sh
```

If your directory looks like this and:

* DNS points to your VPS
* Certificates are valid
* `private_key.pem` is present

…you’re ready to run the install script.
{% endstep %}
{% endstepper %}


# Install via Script

## Quick Start

Download and run the installation script:

```bash
# Download the script
curl -fsSLo rollout_node.sh https://raw.githubusercontent.com/flashgatenetwork/flashgate_installer/refs/heads/main/rollout_node.sh

# Make it executable
chmod +x rollout_node.sh

# Run the installation
sudo ./rollout_node.sh \
  -r eu-central-1 \
  -d mycompany.com \
  -p gcp \
  -o 00000000-0000-0000-0000-000000000000 \
  -k /path/to/private_key.pem \
  -b https://backend.flashback.tech
```

> **Note**: Ensure you have completed all [prerequisites](/guides/private-node-setup/prerequisites) before running the installation script.

## Required Arguments

* `-r <region>` - AWS region (e.g., `eu-central-1`, `us-east-1`)
* `-d <root-domain>` - Your root domain (e.g., `mycompany.com`)
* `-o <org-id>` - Your organization ID
* `-k <private-key-path>` - Path to your RSA private key file

## Optional Arguments

* `-p <provider>` - Cloud provider (e.g., `aws`, `gcp`, `azure`)
* `-b <backend-url>` - Backend URL (default: `https://backend.flashback.tech`)
* `-n <network-json-path>` - Path to `flashgate-network-delegated.json`

## Domain Convention

The script will create these domains:

* `s3-<region>[-<provider>].<root-domain>`
* `gcs-<region>[-<provider>].<root-domain>`
* `blob-<region>[-<provider>].<root-domain>`

## SSL Certificates

You need three certificate pairs that support:

* S3: `s3-<region>[-<provider>].<root-domain>` and `*.s3-<region>[-<provider>].<root-domain>`
* GCS: `gcs-<region>[-<provider>].<root-domain>`
* BLOB: `blob-<region>[-<provider>].<root-domain>` and `*.blob-<region>[-<provider>].<root-domain>`

## Examples

### Using GCP with Let's Encrypt certificates (.crt, .key files)

```bash
sudo ./rollout_node.sh -r eu-central-1 -d mydomain.com -p gcp \
   -o 00000000-0000-0000-0000-000000000000 \
   -k private_key.pem -b https://backend.flashback.tech \
  -1 ~/s3-eu-central-1-gcp.mydomain.com.crt \
  -2 ~/s3-eu-central-1-gcp.mydomain.com.key \
  -3 ~/gcs-eu-central-1-gcp.mydomain.com.crt \
  -4 ~/gcs-eu-central-1-gcp.mydomain.com.key \
  -5 ~/blob-eu-central-1-gcp.mydomain.com.crt \
  -6 ~/blob-eu-central-1-gcp.mydomain.com.key
```

### Using GCP with PFX certificates

```bash
sudo ./rollout_node.sh -r eu-central-1 -d mydomain.com -p gcp \
   -o 00000000-0000-0000-0000-000000000000 \
   -k private_key.pem -b https://backend.flashback.tech \
   -s3pfx ~/s3-eu-central-1-gcp.mydomain.com.pfx \
   -gcspfx ~/gcs-eu-central-1-gcp.mydomain.com.pfx \
   -blobpfx ~/blob-eu-central-1-gcp.mydomain.com.pfx
```

### Using AWS with separate certificate files

```bash
sudo ./rollout_node.sh \
  -r us-east-1 \
  -d mycompany.com \
  -p aws \
  -o 12345678-1234-1234-1234-123456789012 \
  -k ~/private_key.pem \
  -1 ~/s3-us-east-1-aws.crt \
  -2 ~/s3-us-east-1-aws.key \
  -3 ~/gcs-us-east-1-aws.crt \
  -4 ~/gcs-us-east-1-aws.key \
  -5 ~/blob-us-east-1-aws.crt \
  -6 ~/blob-us-east-1-aws.key
```

### Custom backend URL

```bash
sudo ./rollout_node.sh \
  -r eu-central-1 \
  -d mycompany.com \
  -p gcp \
  -o 12345678-1234-1234-1234-123456789012 \
  -k /home/ubuntu/private_key.pem \
  -b https://custom-backend.example.com \
  -s3pfx ~/s3.pfx \
  -gcspfx ~/gcs.pfx \
  -blobpfx ~/blob.pfx
```

## What the Script Does

The `rollout_node.sh` script automates the complete setup of your private Flashgate node:

1. **System Preparation** - Updates system packages and installs Docker with Docker Compose
2. **Directory Setup** - Creates the necessary directory structure under `/opt/flashgate`
3. **Certificate Processing** - Handles SSL certificates in both separate (.crt/.key) and PFX formats
4. **Configuration Generation** - Creates Nginx configuration for reverse proxy and SSL termination
5. **Service Deployment** - Sets up Docker containers for S3, GCS, and Blob APIs
6. **Backend Integration** - Fetches encrypted configuration from the Flashgate backend
7. **Node Registration** - Registers your node with the Flashgate platform
8. **Service Startup** - Starts all services and verifies they're running correctly

The script handles all the complex configuration automatically, ensuring your node is properly integrated with the Flashgate ecosystem.

## Verification

After installation, check that services are running:

```bash
sudo docker ps
sudo docker logs
```


# Explore Use Cases

This section helps you move from “platform setup” to real product scenarios.

The use cases are organized by resource family so teams can quickly find patterns that match their architecture:

* **Cloud Storage** use cases: multi-cloud object data flows, migration patterns, DR, and latency-aware routing.
* **AI LLM** use cases: prompt routing, fallback, governance, and production-ready app integration patterns.

## What you will find in this section

* [**Cloud Storage**](/guides/explore-use-cases/explore-use-cases): practical deployment blueprints for S3/GCS/Azure-compatible operations through Flashgate.
* [**AI LLM**](/guides/explore-use-cases/ai-llm): practical deployment blueprints for OpenAI-compatible AI workloads through Flashgate.

## How to use these guides

1. Start from the problem statement to identify the closest architecture pattern.
2. Follow prerequisites and copy the provided snippets as a baseline.
3. Adapt policies, keys, and endpoints to your organization/repository.
4. Validate in staging before rolling out to production.


# Cloud Storage

This page groups real-world Cloud Storage architecture patterns you can implement with Flashgate.

All scenarios assume you already created buckets, repositories, and API keys in the platform, then consume storage through a Flashgate endpoint.

## Available use cases

* [**Credit-aware multi-cloud storage behind one endpoint**](/guides/explore-use-cases/explore-use-cases/credit-aware-multi-cloud-storage-behind-one-endpoint) Route writes based on provider credits/budget to avoid overages while keeping one client integration.
* [**Cross-cloud migration and vendor-lock-in escape**](/guides/explore-use-cases/explore-use-cases/cross-cloud-migration-and-vendor-lock-in-escape) Migrate workloads incrementally between providers with minimal application changes.
* [**Disaster recovery (DR) / cold-tier backup to DePIN**](/guides/explore-use-cases/explore-use-cases/disaster-recovery-dr-cold-tier-backup-to-depin) Build resilient backup patterns across traditional clouds and decentralized storage tiers.
* [**Latency-aware routing for edge and AI pipelines**](/guides/explore-use-cases/explore-use-cases/latency-aware-routing-for-edge-and-ai-pipelines) Select the best endpoint/node based on live performance metrics to reduce tail latency.

## Expected outcome

After these guides, you should be able to design storage routing and resilience strategies with measurable operational controls (cost, latency, failover).


# Credit-aware multi-cloud storage behind one endpoint

{% hint style="danger" %}
Expiremental Guide: May contain errors as our technology continues to evolve. If you encounter any problems, please do not hesitate to contact us in [Discord](https://discord.com/invite/yy8kyM5qFB) and give us your feedback.
{% endhint %}

## The Problem

Today, developers juggle credits across AWS, GCP, Azure (and sometimes DePIN providers like StorJ/Akave), while each application usually speaks only one storage API. You end up maintaining multiple SDKs, keys, and endpoints; switching providers or enforcing hard limits (“stop writes when free credits are out”) is painful. Visibility is fragmented, and failover is manual.

**Flashgate** gives you a single integration that works across backends. Bridge Nodes speak S3, GCS, or Azure Blob; your app uses one protocol and one set of repo-scoped keys, while Flashgate routes to the bucket/provider you select via policy and statistics. Repositories aggregate multiple vendor buckets and expose usage/latency stats and quotas so you can automatically shift writes as credits are consumed.

***

## Prerequisites

<details>

<summary>Accounts &#x26; resources</summary>

* At least one object bucket/container per provider you want to use (AWS S3, GCS, Azure Blob, optionally DePIN). You can create/link them in Flashgate.
* Use least-privilege credentials for each bucket when you link it.

</details>

<details>

<summary>Flashgate setup</summary>

* Flashgate account with dashboard/API access.
* Create **Buckets** in Flashgate (one per cloud bucket/container you’ll use).
* Create a **Repository** and attach those Buckets.
* Issue **API Keys** for the repository (WRITE for writers, READ for readers). See the API Keys reference for create/list/update/delete of repo-scoped keys, secured by Bearer Token.

</details>

<details>

<summary>Pick a protocol (client SDK)</summary>

Choose the API you will speak from your app; each client instance uses one protocol:

* S3: `boto3` (Python), `@aws-sdk/client-s3` (Node.js), `minio` (Go/Java/etc.)
* GCS: `@google-cloud/storage` (Node.js), `google-cloud-storage` (Python), etc.
* Azure: `azure-storage-blob`

You can mix protocols across services if needed, but each process should keep one active client per protocol.

</details>

<details>

<summary>Bridge Node endpoints (examples with Public Nodes)</summary>

Bridge Node URL pattern: `https://<api>-<region>-<provider>.flashback.tech` (where `<api>` is `s3`, `gcs`, or `blob`). Examples:

* S3: `https://s3-us-east-1-aws.flashback.tech`
* GCS: `https://gcs-eu-central-1-gcp.flashback.tech`
* Azure Blob: `https://blob-eu-central-1-azure.flashback.tech`.

</details>

<details>

<summary>Networking &#x26; security</summary>

* Outbound HTTPS to `*.flashback.tech`.
* Store Flashgate repository API keys in your vault (AWS Secrets Manager, GCP Secret Manager, Azure Key Vault).
* Treat keys like you would cloud provider access keys (rotate, least privilege).

</details>

***

## Step-by-Step Deployment Recommendations

{% stepper %}
{% step %}

### Model your policy (“where do writes go?”)

Two common strategies:

**A. Credit-harvesting (recommended initially):**

* Maintain one bucket per provider (e.g., `app-logs-aws`, `app-logs-gcp`, `app-logs-azure`).
* At write-time, choose the target bucket based on remaining monthly credit/soft-cap per provider.
* Reads may come from any bucket (or a designated “primary”).

**B. Hot+Cold:**

* Write to a hot bucket (closest/fastest), mirror to a cheaper “cold” bucket (DePIN or another cloud) on a schedule.
* Use native provider copy when possible; otherwise Flashgate streams cross-provider. (See storage ops/limits.)

*We’ll implement A below and show where to adapt for B.*
{% endstep %}

{% step %}

### Create Buckets and Repository in Flashgate

**2.1 Create/Link Buckets**

In **Storage → Buckets**, add one bucket per provider. Provide least-privilege credentials/role and validate. (See Bucket endpoints and validation)

**2.2 Create a Repository**

In **Storage → Repositories**, create `app-data` (example) and attach the buckets you created. (Repo CRUD and stats endpoints: `/repo`, `/repo/stats`.)

**2.3 Generate Repository API keys**

**I**n the repository’s **API Keys** tab, create a **WRITE** key for your writers and a **READ** key for read-only flows. Save secrets to your vault. (API keys endpoints under `/repo/{repoId}/apikey`.)
{% endstep %}

{% step %}

### Wire your backend to Flashgate

Create clients that point to a Bridge Node endpoint. Keep a small per-endpoint client cache so you can swap endpoints quickly if you move traffic. (Bridge Nodes and endpoint pattern: see docs.) [docs.flashback.tech](https://docs.flashback.tech/flashgate-platform/bridge-nodes)

**3.1 S3 — Node.js (`@aws-sdk/client-s3`)**

```ts
// fbS3Client.ts
import { S3Client } from "@aws-sdk/client-s3";

const clients = new Map<string, S3Client>();

export function s3ClientFor(endpoint: string, keyId: string, secret: string) {
  if (!clients.has(endpoint)) {
    clients.set(endpoint, new S3Client({
      endpoint,
      region: "us-east-1",           // required by SDK, not used by Flashgate
      credentials: { accessKeyId: keyId, secretAccessKey: secret },
      forcePathStyle: true           // recommended with custom endpoints
    }));
  }
  return clients.get(endpoint)!;
}
```

Usage:

```ts
import { PutObjectCommand } from "@aws-sdk/client-s3";
import { s3ClientFor } from "./fbS3Client";

const ENDPOINT = process.env.FB_S3_ENDPOINT!; // e.g., https://s3-us-east-1-aws.flashback.tech
const KEY_ID = process.env.FB_KEY_ID!;        // repo API key id
const KEY_SECRET = process.env.FB_KEY_SECRET!;// repo API key secret

export async function putS3(bucket: string, key: string, body: Buffer) {
  const s3 = s3ClientFor(ENDPOINT, KEY_ID, KEY_SECRET);
  await s3.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: body }));
}
```

**3.2 S3 — Python (`boto3`)**

```py
# fb_s3_client.py
import boto3
from botocore.client import Config

def s3_client_for(endpoint: str, key_id: str, key_secret: str):
    session = boto3.session.Session(
        aws_access_key_id=key_id, aws_secret_access_key=key_secret
    )
    return session.client(
        "s3",
        endpoint_url=endpoint,
        config=Config(signature_version="s3v4")
    )
```

Usage:

```py
from fb_s3_client import s3_client_for
import os

ENDPOINT = os.environ["FB_S3_ENDPOINT"]
KEY_ID = os.environ["FB_KEY_ID"]
KEY_SECRET = os.environ["FB_KEY_SECRET"]

def put_s3(bucket: str, key: str, body: bytes):
    s3 = s3_client_for(ENDPOINT, KEY_ID, KEY_SECRET)
    s3.put_object(Bucket=bucket, Key=key, Body=body)
```

**3.3 GCS — Node.js (`@google-cloud/storage`) with custom endpoint**

```ts
// fbGcsClient.ts
import { Storage } from "@google-cloud/storage";

let cached: Storage | null = null;

export function gcsClientFor(endpoint: string, keyId: string, keySecret: string) {
  if (!cached) {
    cached = new Storage({
      apiEndpoint: endpoint,     // e.g., https://gcs-eu-central-1-gcp.flashback.tech
      credentials: {
        client_email: keyId,     // if your lib expects SA-shaped creds; otherwise prefer S3 SDK against GCS Bridge
        private_key: keySecret,
      } as any,
      projectId: "flashgate",
    });
  }
  return cached;
}
```

*Note:* many teams standardize on S3 SDKs against Flashgate’s S3 Bridge endpoint even when the underlying bucket is GCS, to avoid OAuth SA constraints.

**3.4 Azure Blob — Node.js (`@azure/storage-blob`) with custom endpoint**

```ts
// fbBlobClient.ts
import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob";

let cached: BlobServiceClient | null = null;

export function blobClientFor(endpoint: string, keyId: string, keySecret: string) {
  if (!cached) {
    const cred = new StorageSharedKeyCredential(keyId, keySecret);
    cached = new BlobServiceClient(endpoint, cred);
  }
  return cached;
}
```

> Tip: You can also stick to S3 across services for simplicity—just use the S3 Bridge endpoint closest to your buckets. Flashgate translates calls to the underlying provider.
> {% endstep %}

{% step %}

### Pull usage/latency statistics (for policy decisions)

You’ll periodically poll usage to know how much credit you’ve consumed and when to switch providers. Minimal fetchers:

```ts
// flashgateStats.ts
const BASE = "https://backend.flashback.tech";
const headers = {
  Accept: "application/json",
  Authorization: `Bearer ${process.env.FB_JWT}` // token with repo access
};

export async function getRepoStats(repoId?: string) {
  const url = repoId ? `${BASE}/repo/stats?repoId=${repoId}` : `${BASE}/repo/stats`;
  const r = await fetch(url, { headers });
  if (!r.ok) throw new Error(`repo stats: ${r.status}`);
  return r.json();
}

export async function getBucketStats(bucketId?: string) {
  const url = bucketId ? `${BASE}/bucket/stats?bucketId=${bucketId}` : `${BASE}/bucket/stats`;
  const r = await fetch(url, { headers });
  if (!r.ok) throw new Error(`bucket stats: ${r.status}`);
  return r.json();
}

export async function getDailyStats() {
  const r = await fetch(`${BASE}/stats/daily`, { headers });
  if (!r.ok) throw new Error(`daily stats: ${r.status}`);
  return r.json();
}

export async function getMinuteStats() {
  const r = await fetch(`${BASE}/stats/minute`, { headers });
  if (!r.ok) throw new Error(`minute stats: ${r.status}`);
  return r.json();
}
```

* Repo statistics endpoint: `GET /repo/stats` (returns repository-level stats).
* Bucket statistics endpoint: `GET /bucket/stats` (returns `totalUploadBytes`, `totalDownloadBytes`, etc.).
* Performance statistics: `GET /stats/daily`, `GET /stats/minute` for daily/minute aggregates.
  {% endstep %}

{% step %}

### Implement the credit-aware bucket chooser

Define soft caps per provider and pick the first bucket still under its cap. If a write fails due to quota or a transient node issue, fall back to the next provider.

```ts
// chooseBucket.ts
import { getRepoStats } from "./flashgateStats";

const ORDER = ["app-logs-gcp", "app-logs-aws", "app-logs-azure"]; // preference order
const SOFT_CAPS = {
  "app-logs-gcp": 0.8,
  "app-logs-aws": 0.8,
  "app-logs-azure": 1.0
};

type BucketMonth = { used_bytes?: number; soft_limit_bytes?: number };

export async function chooseWriteBucket(repoId: string) {
  const stats = await getRepoStats(repoId);
  // Shape may evolve; adapt to your actual response fields.
  const buckets: Record<string, BucketMonth> = stats?.data?.[0]?.buckets ?? {};
  for (const name of ORDER) {
    const used = buckets[name]?.used_bytes ?? 0;
    const limit = buckets[name]?.soft_limit_bytes ?? Number.POSITIVE_INFINITY;
    if (used < (SOFT_CAPS as any)[name] * limit) return name;
  }
  return ORDER[ORDER.length - 1];
}
```

Write path with fallback (S3 example):

```ts
// writeObject.ts
import { PutObjectCommand } from "@aws-sdk/client-s3";
import { s3ClientFor } from "./fbS3Client";
import { chooseWriteBucket } from "./chooseBucket";

const ENDPOINT = process.env.FB_S3_ENDPOINT!;
const KEY_ID = process.env.FB_KEY_ID!;
const KEY_SECRET = process.env.FB_KEY_SECRET!;
const REPO_ID = process.env.FB_REPO_ID!;

async function fallbackBucket(current: string) {
  const order = ["app-logs-gcp", "app-logs-aws", "app-logs-azure"];
  const i = order.indexOf(current);
  return order[(i + 1) % order.length];
}

export async function putObject(key: string, body: Buffer) {
  const s3 = s3ClientFor(ENDPOINT, KEY_ID, KEY_SECRET);
  let bucket = await chooseWriteBucket(REPO_ID);

  try {
    await s3.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: body }));
  } catch (e: any) {
    const msg = String(e?.message ?? e);
    const quota = msg.includes("QUOTA_EXCEEDED") || msg.includes("403") || msg.includes("429");
    if (quota) {
      const alt = await fallbackBucket(bucket);
      await s3.send(new PutObjectCommand({ Bucket: alt, Key: key, Body: body }));
    } else {
      throw e;
    }
  }
}
```

> For latency-first routing, consult node status and minute stats, then apply your credit cap as a gate. (Bridge Node endpoint pattern & status guidance are documented under Bridge Nodes.)
> {% endstep %}

{% step %}

### Configure quotas and alerts

* In your policy, treat `QUOTA_EXCEEDED` (or HTTP 403/429 mapped by your SDK) as a **soft read-only signal** for that bucket/repo and switch to the next provider automatically.
* Poll `stats/daily` to drive dashboards/alerts on usage growth, and `stats/minute` for spikes or SLOs.
* If you attach per-bucket soft limits in your internal config, keep them visible to ops so they match provider credit allocations.
  {% endstep %}

{% step %}

### (Optional) Add a cold tier (Hot+Cold strategy)

* Attach a DePIN (or cheaper cloud) bucket to the same repository.
* Run a periodic copy job from hot → cold. Prefer native provider copy when both buckets are on the same provider/region; otherwise Flashgate will stream cross-provider. (See “Storage API operations” for current coverage/limits.)
* Periodically verify restores (sample reads from cold weekly).

Skeleton (Node):

```ts
import { CopyObjectCommand } from "@aws-sdk/client-s3";
import { s3ClientFor } from "./fbS3Client";

const s3 = s3ClientFor(process.env.FB_S3_ENDPOINT!, process.env.FB_KEY_ID!, process.env.FB_KEY_SECRET!);

export async function mirrorToCold(hotBucket: string, coldBucket: string, key: string) {
  // Use native copy if hot/cold share the same provider/region behind the same Bridge;
  // otherwise stream GetObject -> PutObject to the other provider.
  await s3.send(new CopyObjectCommand({
    Bucket: coldBucket,
    Key: key,
    CopySource: `/${hotBucket}/${encodeURIComponent(key)}`
  }));
}
```

{% endstep %}

{% step %}

### Validate & roll out

**Smoke tests**

* Put/Get/Delete small objects to each provider bucket via Flashgate.
* Force a quota breach in staging; verify writers switch providers or enter read-only mode.

**Performance baseline**

* For each region/provider, measure `HeadObject`/`PutObject` latency and set SLOs.
* Prefer the Bridge Node endpoint closest to your traffic patterns (Bridge Nodes doc shows pattern & examples).

**Gradual rollout**

* Start with low-risk object classes (logs, analytics artifacts).
* Expand to user-visible data once stability and observability are proven.
  {% endstep %}
  {% endstepper %}

***

## Operations Playbook (TL;DR)

* **Endpoints**: Use `https://<api>-<region>-<provider>.flashback.tech`. Keep a per-endpoint client cache.
* **Keys**: Repo-scoped READ/WRITE keys. Store in a vault. Rotate.
* **Routing**: Policy chooses bucket by credit usage (soft caps). On `QUOTA_EXCEEDED`/403/429 → switch. (Use `/repo/stats` & `/bucket/stats`.)
* **Observability**: Poll `/stats/daily` and `/stats/minute` for dashboards/alerts.
* **Resilience**: Keep at least one alternate provider in the repository. Test fallback monthly.
* **Hot+Cold**: Optional mirroring to DePIN or cheaper cloud. Verify restores weekly.
* **Limits**: Some cross-provider operations have constraints; check “Storage API operations” as coverage expands.

### Environment Variables (example)

```
# Bridge endpoint (choose the one that matches your primary protocol/region/provider)
FB_S3_ENDPOINT=https://s3-us-east-1-aws.flashback.tech
# Repo keys (WRITE for writers, READ for read-only flows)
FB_KEY_ID=...
FB_KEY_SECRET=...
# Backend API access (for stats, admin calls)
FB_JWT=...
# Repo identity (used by chooser)
FB_REPO_ID=...
```

### Notes on limitations & compatibility

* Storage operation coverage is improving; basic CRUD is supported. Cross-provider multipart uploads and some advanced features may be limited—design large-file flows accordingly. See Storage API operations status.
* When in doubt, standardize your app on **one** protocol (usually S3) and let Flashgate translate to the underlying bucket/provider.

### References

* **Bridge Nodes**: endpoint pattern and examples (S3/GCS/Azure).
* **Repositories**: create/update/list and stats (`/repo`, `/repo/stats`).
* **API Keys**: repo-scoped key management.
* **Bucket stats**: `GET /bucket/stats` fields (e.g., `totalUploadBytes`, etc.).
* **Performance statistics**: `GET /stats/daily`, `GET /stats/minute`.
* **Explore use cases**: endpoints summary and prerequisites.

### Appendix: Minimal Go example (S3)

```go
// fb_s3_client.go
package flashgate

import (
	"context"
	"net/http"
	"os"
	"strings"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/aws/smithy-go/logging"
)

var clients = map[string]*s3.Client{}

func S3ClientFor(endpoint, keyId, keySecret string) *s3.Client {
	if c, ok := clients[endpoint]; ok {
		return c
	}
	cfg, _ := config.LoadDefaultConfig(context.TODO())
	creds := aws.Credentials{
		AccessKeyID:     keyId,
		SecretAccessKey: keySecret,
	}
	client := s3.NewFromConfig(cfg, func(o *s3.Options) {
		o.BaseEndpoint = aws.String(endpoint)
		o.UsePathStyle = true
		o.Credentials = aws.NewCredentialsCache(aws.StaticCredentialsProvider{Value: creds})
		o.Region = "us-east-1"
		o.HTTPClient = &http.Client{}
		o.Logger = logging.NewStandardLogger(os.Stdout)
	})
	clients[endpoint] = client
	return client
}
```

```go
// put.go
bucket := "app-logs-gcp"
key := "hello.txt"
body := strings.NewReader("hi")
cli := flashgate.S3ClientFor(os.Getenv("FB_S3_ENDPOINT"), os.Getenv("FB_KEY_ID"), os.Getenv("FB_KEY_SECRET"))
_, err := cli.PutObject(context.TODO(), &s3.PutObjectInput{Bucket: &bucket, Key: &key, Body: body})
if err != nil { /* fallback to next bucket */ }
```


# Cross-cloud migration and vendor-lock-in escape

{% hint style="danger" %}
Expiremental Guide: May contain errors as our technology continues to evolve. If you encounter any problems, please do not hesitate to contact us in [Discord](https://discord.com/invite/yy8kyM5qFB) and give us your feedback.
{% endhint %}

## The Problem

Moving data between clouds (S3 ⇄ GCS ⇄ Azure Blob) is painful: every provider has different copy semantics, auth models, and hidden limits. Refactors are common, and you often pay egress plus suffer long cut-overs.

Flashgate lets you keep one client integration while using two migration paths: a provider’s **native copy** (S3 `CopyObject`, GCS `RewriteObject`, Azure `copy_from_url`) when rules allow, or an **emulated copy** streamed by Bridge Nodes when native isn’t possible. This unifies the workflow and makes it easy to test (which path you’re taking) and what it will cost.

***

## Step-by-Step Deployment Recommendations

{% stepper %}
{% step %}

### Model the migration policy

* Prefer **native copy** when the provider allows it (same storage type/provider, and the provider’s region/class/size rules). Otherwise Flashgate **emulates** the copy by streaming, which incurs egress and counts toward Flashgate traffic. Always test with a small object first to confirm cost behavior.

**Signaling which path to use (critical):**

* **S3/Blob native copy:** connect to the Repo; **destination bucket must be attached** to the Repo; the **source bucket must not**; destination credentials must also allow reading the source bucket.
* **GCS native copy:** inverse, **source attached**, **destination not**; source credentials must allow writing to destination.
* **Emulated copy:** attach **both** buckets to the same Repo; credentials may differ.
  {% endstep %}

{% step %}

### Create Buckets & Repository in Flashgate

* **Create/Link Cloud Buckets** in Flashgate
  * For each provider, add a Bucket in the dashboard:\
    “Add Bucket” → select provider → provide credentials/role → validate.
* **Create a Repository**
  * “New Repository” → name it (e.g., `app-data`) → attach all created Buckets.
* **Generate Repository API Keys**
  * Create a **WRITE** key for your application and a **READ** key for services that only read.
  * Save the secret in your vault; you can’t retrieve it later from it.
    {% endstep %}

{% step %}

### Wire your backend client to Flashgate

Create clients pointing at a Bridge Node endpoint; keep a small cache keyed by endpoint so you can swap quickly.

**Python (boto3 / S3)**

```python
# fb_s3_client.py
import boto3
from botocore.client import Config

def s3_client_for(endpoint, key_id, key_secret):
    session = boto3.session.Session(
        aws_access_key_id=key_id, aws_secret_access_key=key_secret
    )
    return session.client("s3", endpoint_url=endpoint, config=Config(signature_version="s3v4"))
```

**Node (aws-sdk v3 / S3)**

```ts
// fbS3Client.ts
import { S3Client } from "@aws-sdk/client-s3";

const clients = new Map<string, S3Client>();
export function s3ClientFor(endpoint: string, keyId: string, secret: string) {
  if (!clients.has(endpoint)) {
    clients.set(endpoint, new S3Client({
      endpoint, region: "us-east-1",
      credentials: { accessKeyId: keyId, secretAccessKey: secret },
      forcePathStyle: true
    }));
  }
  return clients.get(endpoint)!;
}
```

> (Use analogous clients for GCS/Azure if that’s your app’s native protocol.) Flashgate S3 endpoints are compatible with standard S3 SDKs.
> {% endstep %}

{% step %}

### Implement the migration routine

#### **A. Native copy (fast path, usually lowest cost)**

Requirements recap: same provider/type; signal native per step 1; ensure the required cross-bucket permissions. Operations are the platform’s built-ins: S3 `CopyObject`, GCS `RewriteObject`, Azure `copy_from_url`.

**Python (boto3 / S3 CopyObject)**

```python
from config_flashgate_s3 import s3

def copy_native_s3(src_bucket: str, src_key: str, dst_bucket: str, dst_key: str):
  s3.copy_object(
      Bucket=dst_bucket,
      Key=dst_key,
      CopySource=f"{src_bucket}/{src_key}",  # URL-encode if needed
  )
```

**Node (aws-sdk v3 / S3 CopyObject)**

```ts
import { CopyObjectCommand } from "@aws-sdk/client-s3";
import { s3 } from "./configFlashgateS3";

export async function copyNativeS3(srcBucket: string, srcKey: string, dstBucket: string, dstKey: string) {
  await s3.send(new CopyObjectCommand({
    Bucket: dstBucket,
    Key: dstKey,
    CopySource: `${srcBucket}/${encodeURIComponent(srcKey)}`
  }));
}
```

#### **B. Emulated copy (cross-provider or when native is disallowed)**

Attach **both** buckets to the Repo; invoke the same copy operation. Flashgate will stream the bytes between buckets. Expect outgoing traffic charges and count toward Flashgate spend.

> Large files: default single-upload limit is 100 MB; use multipart/resumable uploads for larger objects. (Multipart copy via `UploadPartCopy` is not supported; fall back to a read-then-multipart-put if you need client-side control.)
> {% endstep %}

{% step %}

### Configure quotas & alerts

* Quotas: when exceeded, **repository write operations are disabled**, reads remain available; surface `QUOTA_EXCEEDED` to pause jobs.
* Observability: pull **daily/minute** stats and **node minute** stats to watch throughput/latency and detect hotspots.

```js
const H = { Accept: "application/json", Authorization: `Bearer ${process.env.FB_JWT}` };
const daily  = await fetch("https://backend.flashback.tech/stats/daily",  { headers: H }).then(r=>r.json());
const minute = await fetch("https://backend.flashback.tech/stats/minute", { headers: H }).then(r=>r.json());
```

{% endstep %}

{% step %}

### (Optional) Add a cold tier

Attach a second (cheaper) destination bucket to the Repo and schedule periodic copies from your hot bucket. Prefer native copy when available to avoid traffic charges; otherwise emulated copy will stream and bill egress.
{% endstep %}

{% step %}

### Validate & roll out

* **Dry-run:** copy a tiny object and check the cloud console for whether traffic was billed (confirms native vs emulated).
* **Performance:** pick the closest Bridge Node; bucket details expose Online/Disconnected/Offline and latencies measured via `HeadBucket`.
* **Gradual rollout:** start with low-risk prefixes, then scale up.
  {% endstep %}

{% step %}

### Operation Playbook

* **Keys:** rotate repo keys; secrets are non-recoverable after you leave the page.
* **Quotas:** treat `QUOTA_EXCEEDED` as read-only; resume only after reset or after raising limits.
* **Retry/fallbacks:** if native copy fails with provider rules, retry as emulated by attaching both buckets.
* **Limits:** >100 MB needs multipart/resumable; plan client-side chunking for huge objects.
  {% endstep %}
  {% endstepper %}


# Disaster recovery (DR) / cold-tier backup to DePIN

{% hint style="danger" %}
Expiremental Guide: May contain errors as our technology continues to evolve. If you encounter any problems, please do not hesitate to contact us in [Discord](https://discord.com/invite/yy8kyM5qFB) and give us your feedback.
{% endhint %}

## The Problem

Relying on a single cloud for backups risks vendor outages, policy changes, and pricey “rehydration” from cold tiers. Building a cross-cloud (or DePIN) backup pipeline usually means stitching together different SDKs, auth models, and copy rules, plus figuring out when you’ll pay egress.

Flashgate simplifies this: attach your hot bucket and a cheaper cold bucket to one **Repository**, then copy with a single client. When source/destination allow it, Flashgate uses the provider’s **native copy** (S3 `CopyObject`, GCS `RewriteObject`, Azure `copy_from_url`) to avoid traffic charges; otherwise the Bridge Node **emulates** the copy by streaming bytes between buckets. You can test which path you’re taking on a tiny object and verify billing before moving real data.

***

## Step-by-Step Deployment Recommendations

{% stepper %}
{% step %}

### Define your Backup policy

* **Frequency & scope:** e.g., run hourly/daily on prefixes like `app-data/` and `db-dumps/`.
* **Retention:** decide how long to keep in cold tier (by prefix/date).
* **Large objects:** default per-file operation limit is **100 MB**; plan multipart/resumable uploads for larger backups.
* **Tracking:** keep a small **manifest/checkpoint** (written to your Repo) to avoid recopying objects.
  {% endstep %}

{% step %}

### Create Buckets & Repository in Flashgate

* **Create/Link Cloud Buckets** in Flashgate
  * For each provider, add a Bucket in the dashboard:\
    “Add Bucket” → select provider → provide credentials/role → validate.
  * Select DePin providers for cold storage. Be aware of latency increase.
* **Create a Repository**
  * “New Repository” → name it (e.g., `app-data`) → attach all created Buckets.
* **Generate Repository API Keys**
  * Create a **WRITE** key for your application and a **READ** key for services that only read.
  * Save the secret in your vault; you can’t retrieve it later from it.
    {% endstep %}

{% step %}

### Wire your backend client to Flashgate

Create clients pointing at a Bridge Node endpoint; keep a small cache keyed by endpoint so you can swap quickly.

**Python (boto3 / S3)**

```python
# fb_s3_client.py
import boto3
from botocore.client import Config

def s3_client_for(endpoint, key_id, key_secret):
    session = boto3.session.Session(
        aws_access_key_id=key_id, aws_secret_access_key=key_secret
    )
    return session.client("s3", endpoint_url=endpoint, config=Config(signature_version="s3v4"))
```

**Node (aws-sdk v3 / S3)**

```ts
// fbS3Client.ts
import { S3Client } from "@aws-sdk/client-s3";

const clients = new Map<string, S3Client>();
export function s3ClientFor(endpoint: string, keyId: string, secret: string) {
  if (!clients.has(endpoint)) {
    clients.set(endpoint, new S3Client({
      endpoint, region: "us-east-1",
      credentials: { accessKeyId: keyId, secretAccessKey: secret },
      forcePathStyle: true
    }));
  }
  return clients.get(endpoint)!;
}
```

> (Use analogous clients for GCS/Azure if that’s your app’s native protocol.) Flashgate S3 endpoints are compatible with standard S3 SDKs.
> {% endstep %}

{% step %}

### Implement the backup job (baseline)

**A. Choose the copy path per pair of buckets**

* **Native copy** (lowest cost): only if **same storage type & provider** and provider rules (region/class/size) allow it. Signaling rules:\
  • S3/Azure Blob → **destination attached**, **source not**, dest creds can read source.\
  • GCS → **source attached**, **destination not**, source creds can write to destination.
* **Emulated copy** (cross-provider): attach **both** buckets to the Repo; Flashgate streams data between them. Expect egress + Flashgate traffic counted.

**B. Enumerate & copy**

* **Scan** the hot bucket for new objects since your last checkpoint (manifest stored in the Repo).
* For each object, **try native copy** when eligible; otherwise let Flashgate **emulate** the copy. Native copies typically avoid traffic charges; emulated copies always bill egress.

**C. Schedule**

* Run via cron/K8s Jobs/Cloud Scheduler. Persist checkpoint after each successful batch.

> Tip: Before the first full run, **test with a tiny file** and **check the provider console** for any traffic charges. This confirms whether you’re on the native or emulated path.
> {% endstep %}

{% step %}

### Monitoring & alerts

* Pull **daily** and **minute** stats to track ops, latency, and errors. JWT Bearer required.\
  `GET https://backend.flashback.tech/stats/daily` · `GET https://backend.flashback.tech/stats/minute`
* For per-node visibility (e.g., targeting a specific bucket/region), use\
  `GET /stats/nodes/minute?bucketId=...`.

```js
const H = { Accept: "application/json", Authorization: `Bearer ${process.env.FB_JWT}` };
const daily  = await fetch("https://backend.flashback.tech/stats/daily",  { headers: H }).then(r=>r.json());
const minute = await fetch("https://backend.flashback.tech/stats/minute", { headers: H }).then(r=>r.json());
```

{% endstep %}

{% step %}

### Restore drills (don’t skip!)

* Periodically restore a random sample from the cold tier to prove integrity and measure RTO.
* Remember: some bucket-level features (e.g., versioning, lifecycle rules) are not managed via Flashgate endpoints—plan your policy at the provider.
  {% endstep %}

{% step %}

### Validate & roll out

* **Smoke test:** Put/Get/Delete via Flashgate to both buckets.
* **Cost probe:** tiny copy + console check confirms native vs emulated path.
* **Gradual rollout:** start with low-risk prefixes; then widen.
  {% endstep %}

{% step %}

### Operation Playbook

* **Keys:** rotate Repo keys; secrets are encrypted and not recoverable after creation.
* **Quotas:** set a monthly limit; if `QUOTA_EXCEEDED`, treat Repo as read-only until reset or limit raised.
* **Endpoint choice:** prefer the **closest** Bridge Node; bucket details show node **Online/Disconnected/Offline** and **HeadBucket** latency to guide routing.
* **Large files:** plan multipart/resumable for objects over 100 MB.
  {% endstep %}
  {% endstepper %}


# Latency-aware routing for edge and AI pipelines

{% hint style="danger" %}
Expiremental Guide: May contain errors as our technology continues to evolve. If you encounter any problems, please do not hesitate to contact us in [Discord](https://discord.com/invite/yy8kyM5qFB) and give us your feedback.
{% endhint %}

## The Problem

Today, developers push latency-sensitive workloads (media delivery, feature stores, embeddings, and model shards) to users around the world, but each application typically pins to a single storage endpoint per environment. That means guessing a “best” region, maintaining per-cloud SDK configs, and hard-coding endpoints into services and CDNs, which is brittle and costly. When traffic shifts or a region degrades, failover is manual and risky; keeping regional copies consistent is tedious. On top of that, observability is fragmented across vendor consoles, and there’s no easy way to enforce hard latency SLOs like “prefer sub-50 ms reads and automatically fail over if a node slows down.”

**Flashgate changes this by offering a single integration that works across many regions and providers**. Bridge Node endpoints speak S3, GCS, or Azure Blob so your app only needs one protocol and one credential set, while Flashgate exposes per-node status and measured latency so you can pick the fastest endpoint at runtime. With its repository abstraction, you can attach multiple vendor buckets to one repository and generate reusable READ/WRITE keys that work across all SDKs. The platform also gives you built-in guardrails and observability: minute-level stats and node-level latency you can poll to enforce SLOs, plus quotas that can automatically disable writes once thresholds are met. And because it’s future-proof, you can extend your footprint with additional regions or DePIN edges for cheaper distribution without ever having to re-plumb your app.

***

## Step-by-Step Deployment Recommendations

{% stepper %}
{% step %}

### Model your routing policy

Decide how your client should pick endpoints:

* **Reads:** choose the **fastest Online** Bridge Node for the target bucket/region. Use recent latency; keep a short cache (e.g., 60–120s). If latency spikes or timeouts occur, fail over to the next best node. Use node status/latency that Flashgate measures via `HeadBucket`.
* **Writes:** prefer nodes **geographically close and on the same provider** as the bucket to reduce egress and tail latency; keep the same fallback logic. Bridge Node URLs follow `https://<api>-<region>-<provider>.flashback.tech` with public examples you can start from.
  {% endstep %}

{% step %}

### Create Buckets & Repository in Flashgate

* **Create/Link Cloud Buckets** in Flashgate
  * For each provider, add a Bucket in the dashboard:\
    “Add Bucket” → select provider → provide credentials/role → validate.
  * Select DePin providers for cold storage. Be aware of latency increase.
* **Create a Repository**
  * “New Repository” → name it (e.g., `app-data`) → attach all created Buckets.
* **Generate Repository API Keys**
  * Create a **WRITE** key for your application and a **READ** key for services that only read.
  * Save the secret in your vault; you can’t retrieve it later from it.
    {% endstep %}

{% step %}

### Wire your backend client to Flashgate

Create clients pointing at a Bridge Node endpoint; keep a small cache keyed by endpoint so you can swap quickly.

**Python (boto3 / S3)**

```python
# fb_s3_client.py
import boto3
from botocore.client import Config

def s3_client_for(endpoint, key_id, key_secret):
    session = boto3.session.Session(
        aws_access_key_id=key_id, aws_secret_access_key=key_secret
    )
    return session.client("s3", endpoint_url=endpoint, config=Config(signature_version="s3v4"))
```

**Node (aws-sdk v3 / S3)**

```ts
// fbS3Client.ts
import { S3Client } from "@aws-sdk/client-s3";

const clients = new Map<string, S3Client>();
export function s3ClientFor(endpoint: string, keyId: string, secret: string) {
  if (!clients.has(endpoint)) {
    clients.set(endpoint, new S3Client({
      endpoint, region: "us-east-1",
      credentials: { accessKeyId: keyId, secretAccessKey: secret },
      forcePathStyle: true
    }));
  }
  return clients.get(endpoint)!;
}
```

> (Use analogous clients for GCS/Azure if that’s your app’s native protocol.) Flashgate S3 endpoints are compatible with standard S3 SDKs.
> {% endstep %}

{% step %}

### Discover nodes and pull live latency

List active nodes (bootstrap) and then poll **node minute stats** (optionally filtered by `bucketId`) to get availability and recent latency.

```js
// fbNodeStats.js
const H = { Accept: "application/json", Authorization: `Bearer ${process.env.FB_JWT}` };

export async function listNodes() {
  const r = await fetch("https://backend.flashback.tech/node", { headers: H });
  return r.json(); // includes node metadata for routing tables
}

export async function nodeMinuteStats(bucketId) {
  const url = new URL("https://backend.flashback.tech/stats/nodes/minute");
  if (bucketId) url.searchParams.set("bucketId", bucketId);
  const r = await fetch(url, { headers: H });
  return r.json(); // includes per-node minute latency/ops
}
```

{% endstep %}

{% step %}

### Select the fastest Online node (with TTL + circuit breaker)

```ts
// pickEndpoint.ts
import { listNodes, nodeMinuteStats } from "./fbNodeStats";

const CACHE_TTL_MS = 60_000;
let cache = { endpoint: "", expires: 0 };

export async function pickEndpointFor(bucketId?: string) {
  const now = Date.now();
  if (cache.endpoint && cache.expires > now) return cache.endpoint;

  const nodes = await listNodes();                      // seed candidates
  const stats = await nodeMinuteStats(bucketId);        // recent latency/availability

  // Rank Online nodes by recent latency; fall back to others if needed
  const online = rankByLatency(merge(nodes, stats)).filter(n => n.status === "Online");
  const chosen = (online[0] ?? rankByLatency(merge(nodes, stats))[0]);
  cache = { endpoint: chosen.endpoint, expires: now + CACHE_TTL_MS };
  return cache.endpoint;
}

// If a request times out or 5xx, invalidate cache so next call re-picks:
export function reportFailure() { cache.expires = 0; }
```

(Your “merge” and “rank” functions use the per-node latency fields from the stats response.)
{% endstep %}

{% step %}

### Use the chosen endpoint for reads/writes

```ts
// fbStorage.ts
import { PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { s3ClientFor } from "./fbS3Client";
import { pickEndpointFor, reportFailure } from "./pickEndpoint";

const KEY_ID = process.env.FB_KEY_ID!, SECRET = process.env.FB_KEY_SECRET!;

export async function putObject(bucket: string, key: string, body: Buffer) {
  const endpoint = await pickEndpointFor(bucket);
  const s3 = s3ClientFor(endpoint, KEY_ID, SECRET);
  try {
    await s3.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: body }));
  } catch (e) { reportFailure(); throw e; }
}

export async function getObject(bucket: string, key: string) {
  const endpoint = await pickEndpointFor(bucket);
  const s3 = s3ClientFor(endpoint, KEY_ID, SECRET);
  try {
    return await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
  } catch (e) { reportFailure(); throw e; }
}
```

(Set your endpoint strings using the URL pattern and public examples.)
{% endstep %}

{% step %}

### (Optional) Pre-signed URLs for clients/CDNs

If browsers or edge workers fetch directly, generate a pre-signed URL **against the chosen endpoint** so traffic hits the fastest node without proxying through your backend. (The SDK list includes `@aws-sdk/s3-request-presigner`.)
{% endstep %}

{% step %}

### Observe & alert on latency/SLOs

Build basic dashboards and alerts from **minute** and **daily** stats; keep an eye on tail latency and error rates.

* `GET /stats/nodes/minute?bucketId=...` for per-node latency/availability.
* `GET /stats/minute` and `GET /stats/daily` for repo/bucket ops and latency trends.
  {% endstep %}

{% step %}

### Validate & roll out

* **Smoke test:** list buckets and transfer a small object via your chosen nodes/endpoints.
* **Failover drill:** temporarily block the top endpoint to ensure your circuit breaker selects the next best node and retries.
* **Tune TTL:** start with 60–120s; shorten if your workloads see rapid regional swings.
  {% endstep %}

{% step %}

### Operations playbook

* **Keys:** rotate repo keys; secrets are encrypted, decrypted only in Bridge Node memory; not recoverable later.
* **Health signals:** bucket detail view surfaces **Online/Disconnected/Offline** and **HeadBucket** latency—use these to debug routing.
* **Endpoints:** keep at least two Bridge Node URLs per protocol handy (e.g., `s3-us-east-1-aws.flashback.tech` and one in the EU).
* **Monitoring:** alert when node latency breaches your SLO or when read/write error rates spike; pull from `/stats/nodes/minute` plus minute/daily stats.
  {% endstep %}
  {% endstepper %}


# AI LLM

This page introduces practical AI application patterns built on Flashgate’s OpenAI-compatible AI Gateway.

The goal is to help teams deploy production-grade LLM workflows with:

* centralized credential management,
* repository-level API keys,
* policy enforcement and observability,
* model/provider portability.

## Available use cases

* [**Multi-model fallback and reliability routing**](/guides/explore-use-cases/ai-llm/multi-model-fallback-and-reliability-routing)
* [**Cost guardrails with automatic model tiering**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**PII-safe support assistant with policy enforcement**](/guides/explore-use-cases/ai-llm/pii-safe-support-assistant-with-policy-enforcement)
* [**RAG knowledge assistant over multi-cloud storage**](/guides/explore-use-cases/ai-llm/rag-knowledge-assistant-over-multi-cloud-storage)

## Before you start

Make sure you have:

1. At least one configured AI provider in Flashgate (AI → AI LLM).
2. A repository exposing an OpenAI-compatible endpoint.
3. Repository API keys for your application.
4. Optional governance rules in AI Policy for production workloads.


# Multi-model fallback and reliability routing

{% hint style="danger" %}
Experimental guide: validate every workflow in staging before production.
{% endhint %}

## The Problem

LLM applications fail in production for reasons that are often outside your code:

* transient provider outages,
* strict per-model rate limits,
* model-specific latency spikes,
* regional instability.

If your app is hard-wired to one model endpoint, uptime and user experience degrade immediately.

## The Flashgate Pattern

Use one Flashgate repository as your stable OpenAI-compatible integration point, then configure multiple AI LLM resources behind it.

Your application keeps one API contract, while your routing layer applies fallback order by model/provider when calls fail or exceed SLOs.

## Prerequisites

* Flashgate repository configured for **OpenAI** endpoint type.
* At least two configured AI LLM resources (for example OpenAI + Anthropic-compatible endpoint).
* Repository API key (AI usage).
* Basic request telemetry (latency, failures, model used).

Reference pages:

* [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1)
* [Build a Repository](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1)
* [AI LLM APIs](/support-reference/platform-api-reference/ai-apis/ai-llms)

## Implementation blueprint

{% stepper %}
{% step %}

### Define fallback tiers

Example policy:

1. **Tier 1**: high-quality model for normal traffic.
2. **Tier 2**: similar quality but lower latency / alternate provider.
3. **Tier 3**: low-cost baseline for graceful degradation.

Use deterministic rules so behavior is easy to debug.
{% endstep %}

{% step %}

### Configure one client against Flashgate

```python
# fb_openai_client.py
from openai import OpenAI
import os

client = OpenAI(
    base_url=os.environ["FB_OPENAI_BASE_URL"],  # e.g. https://openai-us-east-1-aws.flashback.tech/v1
    api_key=os.environ["FB_API_KEY_SECRET"]
)
```

Use environment variables:

```bash
export FB_OPENAI_BASE_URL="https://openai-us-east-1-aws.flashback.tech/v1"
export FB_API_KEY_SECRET="<repo_api_key_secret>"
```

{% endstep %}

{% step %}

### Add fallback execution in application code

```python
# fallback_completion.py
from fb_openai_client import client

MODEL_PRIORITY = [
    "gpt-4.1",        # Tier 1
    "gpt-4.1-mini",   # Tier 2
    "gpt-4o-mini"     # Tier 3
]

def complete_with_fallback(messages):
    last_error = None
    for model in MODEL_PRIORITY:
        try:
            res = client.chat.completions.create(
                model=model,
                temperature=0.2,
                messages=messages,
                timeout=20
            )
            return {
                "model": model,
                "content": res.choices[0].message.content,
                "usage": res.usage
            }
        except Exception as e:
            last_error = e
    raise RuntimeError(f"All model tiers failed: {last_error}")
```

{% endstep %}

{% step %}

### Add reliability controls

* Per-tier timeout (e.g., 20s → 12s → 8s).
* Retry with exponential backoff before tier switch.
* Circuit breaker: temporarily remove a failing tier after N consecutive failures.
* Emit structured logs (`request_id`, `tier`, `model`, `latency_ms`, `status`).
  {% endstep %}

{% step %}

### Validate in staging

Run synthetic checks every minute:

```bash
curl -sS "$FB_OPENAI_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $FB_API_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "model":"gpt-4.1-mini",
    "messages":[{"role":"user","content":"healthcheck"}],
    "max_tokens":8
  }'
```

Track:

* success rate by model,
* p95 latency by model,
* fallback activation rate.
  {% endstep %}
  {% endstepper %}

## Production checklist

* Keep at least 2 providers/models available.
* Cap fallback depth to avoid runaway latency.
* Alert when Tier 1 success rate drops below threshold.
* Review routing weekly using usage statistics and error trends.


# Cost guardrails with automatic model tiering

## Introduction

As organizations scale their AI features and workflows in production, AI/LLM costs can quickly escalate out of control. Without guardrails and intelligent routing, high-volume and straightforward tasks might be processed by premium, high-cost models unnecessarily.

"Cost guardrails with automatic model tiering" is an architectural pattern that ensures requests are routed dynamically based on task complexity, budget limits, token costs, and repository-level usage bounds.

This guide serves as a practical deployment blueprint for engineering teams using **Flashgate** to configure an AI gateway that seamlessly routes requests to the right model tier (OpenAI, Anthropic, Gemini, etc.) while enforcing cost controls, repository-level governance, and fallback logic—without leaking provider-specific complexity into application code.

## The Problem

When engineering teams first integrate LLMs, the path of least resistance is often hardcoding a premium model for all requests. As adoption grows, this approach faces severe challenges:

* **Unnecessary Spending**: Simple tasks like extracting a date or summarizing a small snippet run on premium models instead of highly capable, cheaper alternatives.
* **Runaway Costs**: Unchecked bugs, infinite loops, or sudden traffic spikes can drain AI budgets overnight.
* **Provider Lock-in & Coupling**: Application logic becomes heavily tied to a single provider's API structure, making it a massive engineering effort to migrate or add multi-model support.
* **Lack of Governance**: Without repository-scoped attribution, it is impossible to know which project, user, or codebase is responsible for the AI usage and cost.
* **Brittleness**: Without fallback mechanisms, a provider outage or rate limit (429/5xx) leads to complete application failure.

## Why This Matters in Production

Enterprise deployment of AI requires predictability, observability, and resilience.

* **Finance and FinOps teams** need predictable budgets and clear attribution to understand ROI.
* **Operations teams** need to be able to throttle usage, switch providers, or degrade gracefully during incidents without redeploying the application.
* **Engineering teams** need a clean surface area where AI operations just work, utilizing stable client libraries rather than maintaining custom routing and resilience code.

Implementing automatic model tiering directly impacts the bottom line while simultaneously improving the developer experience and system reliability.

## How Flashgate Fits This Use Case

Flashgate is a centralized enterprise Cloud and AI Gateway that solves these problems at the infrastructure layer, unifying access, governance, and routing across multiple providers.

Instead of your application authenticating directly with OpenAI, Anthropic, or Gemini, it communicates securely with Flashgate using a singular, stable **OpenAI-compatible AI endpoint**.

Flashgate facilitates this architecture through several native capabilities:

* **Repositories**: In Flashgate, repositories are the central scope. Resources, AI API keys, governance policies, and statistics are all tied back to specific repositories, giving you instant usage visibility.
* **Workspace-Level Resources**: AI LLM resources are configured once at the workspace/platform level (abstracting provider credentials like AWS IAM roles or GCP Service Accounts) and then selectively attached to repositories.
* **Unified Interface**: Flashgate handles the translation between provider-specific APIs and its generic OpenAI-compatible endpoint.
* **AI Policy and Usage Statistics**: Flashgate enforces AI policy out-of-the-box and generates rich AI statistics so you understand exactly what operations are consuming tokens and budget.

## Target Architecture

The target architecture decouples the Application Layer from the AI Provider Layer via Flashgate.

1. **Application Layer**: A provider-agnostic business service (e.g., Code Repository Analyzer) uses a standard OpenAI SDK to call Flashgate.
2. **Gateway Layer (Flashgate)**: Exposes a repository-scoped API key and routes incoming requests based on the requested model name. It enforces AI policy and records AI usage statistics.
3. **Provider Layer**: The underlying AI LLM resources (OpenAI, Anthropic, Gemini).

In this architecture, the application determines the *tier* of the task and requests a virtual model name corresponding to that tier. Flashgate then routes the request securely to the configured backend provider.

## Example Scenario: Repository Analysis Across OpenAI, Anthropic, and Gemini

Imagine a company building an internal developer portal that features a **Repository Analysis Service**. This workload is isolated via its own Flashgate repository (`acme-monorepo`) and needs to handle varied tasks mapping to different complexity requirements:

* **Budget Tier (e.g., Gemini Flash)**: Summarize small files, generate README drafts, basic code linting.
* **Balanced Tier (e.g., Anthropic Claude Haiku or OpenAI GPT-4o-mini)**: Analyze standard module architecture, compare common design patterns.
* **Premium Tier (e.g., OpenAI o1 or Claude 3.5 Sonnet)**: Deep, multi-file code understanding, identifying complex security vulnerabilities, or generating intricate migration recommendations.

The service must dynamically pick a tier based on the file count, estimated tokens, task criticality, and remaining repository budget. If the budget is low, tasks fall back to a cheaper tier or reject the request entirely.

## Prerequisites

Before implementing the code, ensure you have:

1. A Flashgate Workspace setup.
2. Administrative access to configure resources and repositories.
3. Node.js/TypeScript or Python environment ready.
4. An understanding of Flashgate’s resource model (Platform/Workspace vs. Repository scope).

## What to Configure in Flashgate Before Coding

1. **Configure AI LLM Resources**: Set up your OpenAI, Anthropic, and Gemini resources at the Flashgate workspace level.
2. **Build a Repository**: Create a dedicated repository (e.g., `repo_demo_code_analysis`) for this specific workload.
3. **Attach Resources**: Attach the AI LLM resources you created to this repository.
4. **Generate AI API Keys**: Issue a repository-scoped AI API Key specifically for this repository's workloads. *Remember: AI API keys are separate from standard storage credentials.*

## Related Flashgate Guides to Read First

To successfully set up the infrastructure, please refer to the following Flashgate documentation pages:

* [**Configuring an AI LLM Resource**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**Adding Resources**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**Building a Repository**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**Attaching Resources to a Repository**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**Configuring External or Delegated Credentials**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**AI API Keys**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering) and [**Authentication**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**Testing a Repository**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**Supported SDKs**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering) and [**Supported AI API Operations**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**Conversation API**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**AI Policy**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)
* [**AI Usage Statistics**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering) and [**Repository Statistics**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering)

## Design Principles

1. **Provider-Agnostic App Layer**: The application code should never reference `anthropic` or `gemini` tightly in its SDK integration. It should solely rely on the OpenAI-compatible SDK provided targeting Flashgate’s base URL.
2. **Fail Fast and Gracefully**: Implement automatic fallbacks for 429s (Too Many Requests), 5xx errors, and timeouts.
3. **Environment-Driven Configuration**: Model names, base URLs, and keys must be injected via environment variables.
4. **Cost Transparency First**: Calculate a token estimate *before* dispatching a prompt and assert it against the remaining daily/monthly budget.
5. **No Hardcoded Secrets**: Use a secure vault, secret manager, or strict environment injection for all keys.

## Cost Guardrails Design

A robust cost guardrail system needs both **proactive checks** and **reactive limits**:

* **Proactive**: A `CostGateway` wrapper that estimates the input tokens of the prompt. If `estimated_cost > remaining_budget`, the request is blocked or downgraded *before* reaching Flashgate.
* **Reactive**: Flashgate's native **AI Policy** restricts the overall maximum spend or token throughput at the repository level.

### Budget Concepts

* **Soft Threshold (e.g., 80% used)**: Trigger alerts and automatically downgrade all "Premium" and "Balanced" tasks to "Budget" tasks when applicable.
* **Hard Threshold (e.g., 100% used)**: Reject all non-critical tasks. Only tasks flagged with a severe escalation rule on the "Premium" tier are allowed, ultimately governed safely by Flashgate's underlying policy restrictions.

## Automatic Model Tiering Design

Tasks are classified not by the *model* they want, but by the *capabilities* they need.

| Tier         | Characteristics                                                  | Virtual Model String |
| ------------ | ---------------------------------------------------------------- | -------------------- |
| **Budget**   | Fast, extremely cheap, simple text manipulation (README drafts). | `FB_MODEL_BUDGET`    |
| **Balanced** | Average cost, good reasoning, everyday code analysis.            | `FB_MODEL_BALANCED`  |
| **Premium**  | High latency, expensive, highly complex logical derivations.     | `FB_MODEL_PREMIUM`   |

When a request arrives, the `ModelTieringService` determines the target baseline tier based on prompt length and task classification, and then checks the `CostGateway` to see if a downgrade is necessary due to budget constraints.

## Repository-Level Usage and Budget Visibility

Because Flashgate routes everything through a specific repository contextualized by its API key, all underlying usage (tokens, request counts, durations) is natively and immutably tracked.

Operators should surface **Flashgate AI Usage Statistics** and **Repository Statistics** directly to finance or platform engineering dashboards. However, to execute real-time application decisions (like triggering a tier switch natively in code), the application should optionally track a sliding-window estimate in memory and synchronize periodically with Flashgate's authoritative metrics.

## Cost Table and Routing Table

> **Note:** All costs listed below are illustrative examples. Always verify current pricing on the provider's official pricing pages before production use.

| Provider      | Model Name          | Suggested Tier | Input Token Cost (1M) | Output Token Cost (1M) | Best-Fit Use Case                                          | Tradeoffs / Recommendation Notes                                            |
| ------------- | ------------------- | -------------- | --------------------- | ---------------------- | ---------------------------------------------------------- | --------------------------------------------------------------------------- |
| **Google**    | `gemini-1.5-flash`  | **Budget**     | $0.075                | $0.30                  | Summarizations, regex parsing, simple drafting.            | Very low cost, fast TTFT. May struggle with deep logical nuance.            |
| **OpenAI**    | `gpt-4o-mini`       | **Budget**     | $0.150                | $0.60                  | Standard classification, JSON extraction, code linting.    | Highly available, great baseline consistency for cheap generic tasks.       |
| **Anthropic** | `claude-3-haiku`    | **Balanced**   | $0.250                | $1.25                  | Standard code review, PR summaries, structure analysis.    | Excellent balance of speed, cost, and code-understanding logic.             |
| **Anthropic** | `claude-3-5-sonnet` | **Premium**    | $3.00                 | $15.00                 | Multi-file architecture analysis, finding obscure bugs.    | noticeably higher cost. Reserve only for explicitly complex code reasoning. |
| **OpenAI**    | `o1-preview`        | **Premium**    | $15.00                | $60.00                 | Complex reverse engineering, undocumented system analysis. | Very slow and expensive. Use only with hard budget thresholds.              |

## Suggested Project Structure

Structuring your project effectively ensures the routing logic remains isolated from specific business workflows.

<details>

<summary>TypeScript / JavaScript Structure</summary>

```
/src
  /config
    models.ts            # Defines tiers and associated model names
    providers.ts         # Maps to Flashgate endpoint configs
    budgets.ts           # Defines soft/hard cost thresholds and daily budgets
  /lib
    flashgate.ts         # Flashgate OpenAI client initialization
    openaiClient.ts      # Wraps SDK with centralized timeout configurations
  /services
    costGateway.ts       # Proactive budget checking & token estimation
    modelTiering.ts      # Tier selection logic (upgrade/downgrade rules)
    repositoryAnalyzer.ts# The primary code-analysis business logic
    usageReporter.ts     # Aggregates usage metrics for local observability
    fallbacks.ts         # 429/5xx retry and tier fallback strategies
  /types
    budget.ts
    usage.ts
  index.ts               # Application entry point
.env.example             # Documented example keys and configurations
package.json
README.md
```

</details>

<details>

<summary>Python Structure</summary>

```
/app
  /config
    models.py            # Defines tiers and associated model names
    providers.py         # Maps to Flashgate endpoint configs
    budgets.py           # Defines soft/hard cost thresholds
  /lib
    flashgate.py         # Flashgate OpenAI client initialization
    openai_client.py     # Wraps SDK with retries and timeout logic
  /services
    cost_gateway.py      # Proactive budget checking & token estimation
    model_tiering.py     # Tier selection logic (upgrade/downgrade rules)
    repository_analyzer.py # The primary code-analysis business logic
    usage_reporter.py    # Aggregates usage for local observability
    fallbacks.py         # 429/5xx retry and tier fallback strategies
  /types
    budget.py
    usage.py
  main.py                # Application entry point
.env.example             # Documented example keys and configurations
pyproject.toml           # (or requirements.txt)
```

</details>

## Environment Variables and Secret Management

> **Security Warning:** Never hardcode credentials. Ensure sample values are noticeably fake. Do not log Flashgate repository scopes, API keys, or raw text prompts context locally. Always isolate production from staging.

Use `.env` files for local development and a secure vault for production runtime injection.

**`.env.example`**

```env
# Define the Flashgate OpenAI-compatible endpoint
FB_OPENAI_BASE_URL=https://openai-us-east-1-aws.flashback.tech/v1

# The repository-scoped API key. Secure this aggressively.
FB_OPENAI_API_KEY=fb_ai_example_key_123456

# Flashgate Governance Context (used for local app tracking / metadata tags)
FB_REPO_ID=repo_demo_code_analysis

# Virtual Configurations representing mapping providers/models to local app tiers
OPENAI_PROVIDER_NAME=openai-prod
ANTHROPIC_PROVIDER_NAME=anthropic-balanced
GEMINI_PROVIDER_NAME=gemini-budget

FB_MODEL_BUDGET=gemini-1.5-flash
FB_MODEL_BALANCED=claude-3-haiku
FB_MODEL_PREMIUM=gpt-4o

# Global Budget Limits
DAILY_BUDGET_USD=50.00
MONTHLY_BUDGET_USD=800.00
```

## Code Implementations

To keep this guide concise, the complete TypeScript and Python implementation source code is available in our fully-documented demonstration repository:

[**Flashgate Cost Guardrails Demonstration Repository**](https://github.com/flashgatenetwork/flashgate-cost-guardrails-demo)

This repository provides foundational codebase examples showing a provider-agnostic router wrapped against Flashgate's universal endpoint. It includes:

* Proactive Budget Checking (`costGateway` / `cost_gateway.py`)
* Dynamic Model Tier Selection (`modelTiering` / `model_tiering.py`)
* Main Application Logic (`repositoryAnalyzer` / `repository_analyzer.py`)
* Resilience and Retry Strategies (`fallbacks` / `fallbacks.py`)
* Usage Aggregation (`usageReporter` / `usage_reporter.py`)

You can explore the directory structure and run the code directly by cloning the repository.

## End-to-End Request Flow

1. **Task Initialization**: The application receives a request to summarize `payments-core` repository logic.
2. **Cost Estimation**: `services/costGateway` intercepts and estimates the prompt cost (e.g. roughly 5,000 tokens).
3. **Threshold Check**: The app calculates remaining local budget bounds. It notes that the budget is at 82% (Soft Threshold exceeded).
4. **Tier Selection**: `services/modelTiering` downgrades the request to the `BUDGET` tier (e.g., `gemini-1.5-flash`), superseding the original `BALANCED` system classification.
5. **Gateway Dispatch**: The Flashgate client dispatches an OpenAI-compatible request injecting `model="gemini-1.5-flash"`.
6. **Flashgate Routing**: Flashgate authenticates the request via the repository-scoped API key. It evaluates global AI Policy limits natively, proxies the payload safely to Google Cloud in the background, translates the payload structure automatically back to OpenAI formats, and permanently chronicles the underlying usage in the statistics reporting tool.
7. **Response Target**: The application seamlessly receives a normalized response text and acts on it without breaking contracts.

## Testing and Validation

Before pushing production changes, comprehensively test the integration locally:

1. **Verify Sandbox Connectivity**: Interactively test your configured repository utilizing the steps documented in [**Testing a Repository**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering).
2. **Validate Fallback Behavior in Staging**: Intentionally simulate provider 429 timeout errors either by triggering malformed payload thresholds or manipulating internal rate throttles explicitly on the external provider console. Ensure your app cascades appropriately to alternative models.
3. **Key Isolation Audits**: Confirm that standard non-AI storage credentials reject explicitly when inadvertently bound to the model generation requests.

## Observability and Operations

Flashgate shifts the heavy burden of distributed observability straight to the platform layer.

* **What to Monitor**: Proactively track AI API successes, 429 escalation spikes, and aggregated monthly usage pipelines directly inside the real-time [**Repository Statistics**](/guides/explore-use-cases/ai-llm/cost-guardrails-with-automatic-model-tiering) console.
* **What to Alert On**: Systematically structure Flashgate alerts concerning excessive token spikes or 500-level degradations. From the application logic level, merely alert upon constant `fallbacks.ts` cascading failures.
* **Provider Unavailability Mitigation**: Should Anthropic suddenly degrade operations globally, an operator may swiftly and confidently flip `FB_MODEL_BALANCED` referencing variables in their pipeline directly to `gpt-4o-mini` without waiting for length continuous integration builds.

## Security and Governance Recommendations

1. **Mandate Vault Integration**: Mandate that variables like `FB_OPENAI_API_KEY` are rigidly consumed entirely localized from a secure secret manager. never hardcode standard string representations.
2. **Key Rotations**: Practice rotating Flashgate AI Keys per standard enterprise compliance. Because keys map solely natively at scoped levels, rotating keys does not trigger unpredicted macroscopic failures scaling horizontally across unrelated repos.
3. **Poka-Yoke Default Architectures**: Programmatically enforce a balanced default. Only explicitly upgrade constraints to premium resources parameterized meticulously by defined operations.
4. **Audit Governance Behaviors**: Routinely evaluate Flashgate statistical logs analyzing users bypassing local cost tiers by hardcoding raw premium model strings independently against API logic.

## Common Pitfalls

* **Provider Coupling**: Integrating tightly-coupled provider-specific vendor SDKs (e.g. direct GCP SDK binaries) straight into primary business blocks rather than uniformly utilizing Flashgate's standardized OpenAI interfaces.
* **Missing Attribution**: Bundling isolated product infrastructures generically onto identical singular Flashgate repositories, effectively sabotaging visibility mechanisms into cost spikes.
* **Hardcoding Cost Metrics**: Utilizing static magic numbers and stale pricing evaluations locked deep within code logic instead of surfacing pricing tiers into easily parsed JSON configuration blocks actively monitored.
* **Exposing Secrets Globally**: Surfacing API keys context directly mapped adjacent to generic text inputs in raw application debug dumps or monitoring aggregates.
* **Omitting Fallbacks Strategies**: Lack of overarching try/catch retry blocks around the SDK endpoints resulting in explicit error exceptions forcefully cascading straight to frontend consumers upon generic cloud variability hits.
* **Not Checking Flashgate Compatibility**: Assuming a brand new foundation model architecture natively processes correctly without auditing the comprehensive Flashgate officially supported AI Operations directories.

## Production Rollout Recommendations

1. **Phase 1 (Shadow Initialization)**: Deploy the entire model tiering logic transparently, logging mathematically downgraded outcomes without definitively replacing baseline inferences natively. Calculate actual proposed variance against practical real world traffic.
2. **Phase 2 (Staging)**: Aggressively instate hard budget constraints artificially inside simulated staging pipelines. Intentionally starve sandbox accounts evaluating that code cascades fail-safely accurately.
3. **Phase 3 (General Availability)**: Officially release leveraging a "fail-open" default (do not fundamentally break client application requests if only the localized tracker stalls offline) fully embracing Flashgate’s embedded backend AI Policy as the ultimate defense against unconstrained consumption.

## Extensions and Next Steps

* Iteratively expand internal estimation systems through real-time tokenizer byte-pair encodings (e.g. `tiktoken`) precisely computing pre-dispatch metrics.
* Configure webhooks triggering automatically bridging anomalous Flashgate thresholds immediately into organizational Slack observability pipelines or SIEM aggregation systems.
* Further context-aware optimization deployments comprehensively via our comprehensive guides establishing complex **RAG Pipelines**.

## Conclusion

Implementing cost guardrails and automatic model tiering isn't a luxury—it is an absolute foundational prerequisite guaranteeing scalable AI product velocity. By structurally leaning upon Flashgate establishing explicit boundary limits, abstracting erratic provider API landscapes, and aggressively enforcing localized repository accountability metrics, engineering environments free themselves entirely managing infrastructure chaos allowing them solely to build. Leverage these blueprints explicitly mitigating runtime volatility, collapsing unexpected vendor bills, and ensuring every single dispatched token fundamentally scales parallel aligned to transparent business necessity.


# PII-safe support assistant with policy enforcement

## The Problem

Customer support copilots process sensitive text (emails, addresses, order data, account identifiers). Without safeguards, prompts may leak PII or generate non-compliant responses.

## The Flashgate Pattern

Combine:

1. **Repository-scoped AI access** (isolated keys),
2. **AI policies** (log / alert / block by risk),
3. **Application redaction** before model calls,
4. **Violation monitoring** for audits.

## Prerequisites

* AI repository and API key dedicated to support workflows.
* AI policy configured for PII and restricted disclosures.
* Ticketing payload schema with fields that can contain PII.

References:

* [AI Policy API reference](/support-reference/platform-api-reference/ai-apis/ai-policy)
* [AI LLM configuration](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1)

## Implementation blueprint

{% stepper %}
{% step %}

### Create and scope policy

Define policies at repository scope for support use cases:

* block full payment-card patterns,
* alert on personal addresses and phone numbers,
* disallow speculation outside official KB.

Use policy actions by severity:

* **Block** for critical data exfiltration patterns,
* **Alert** for risky but reviewable outputs,
* **Log** for observability-only checks.
  {% endstep %}

{% step %}

### Redact sensitive input in app layer

```python
import re

def redact_pii(text: str) -> str:
    text = re.sub(r"\b\d{16}\b", "[REDACTED_CARD]", text)
    text = re.sub(r"[\w\.-]+@[\w\.-]+", "[REDACTED_EMAIL]", text)
    text = re.sub(r"\+?\d[\d\s\-]{7,}\d", "[REDACTED_PHONE]", text)
    return text
```

Always keep the original payload only in your secure system of record.
{% endstep %}

{% step %}

### Enforce answer boundaries

System message example:

```
You are a customer support assistant.
Use only approved knowledge snippets provided in context.
Never reveal secrets, internal IDs, or personal user data.
If missing information, ask for escalation.
```

Keep this instruction template versioned.
{% endstep %}

{% step %}

### Invoke AI through Flashgate endpoint

```bash
curl -sS "$FB_OPENAI_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $FB_API_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "model":"gpt-4.1-mini",
    "messages":[
      {"role":"system","content":"You are a compliant support assistant..."},
      {"role":"user","content":"Help me answer this ticket safely."}
    ]
  }'
```

{% endstep %}

{% step %}

### Monitor violations and alerts

Operationalize daily review:

* policy violations trend,
* blocked request samples,
* false positives requiring policy tuning,
* escalations triggered by assistant uncertainty.

Integrate alerts into Slack/PagerDuty if violation rate spikes.
{% endstep %}
{% endstepper %}

## Expected outcome

A support assistant architecture with clear compliance guardrails, auditable controls, and reduced sensitive-data exposure risk.


# RAG knowledge assistant over multi-cloud storage

## The Problem

Documentation and internal knowledge are spread across buckets/providers and updated by many teams. Centralizing everything first can delay AI feature delivery.

## The Flashgate Pattern

Use Flashgate to unify access:

* Cloud documents are accessed via repository storage endpoints.
* AI generation runs via repository OpenAI-compatible endpoints.
* One control plane handles keys, observability, and policies.

This allows phased RAG adoption without a single-provider lock-in.

## Prerequisites

* Storage resources connected in Flashgate (S3/GCS/Azure-compatible).
* AI LLM provider connected in Flashgate.
* Repository configured with both storage and AI resources.
* Chunking/indexing pipeline in your application stack.

References:

* [Cloud Storage use cases](/guides/explore-use-cases/explore-use-cases)
* [Build a Repository](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage-1)

## Architecture flow

1. **Ingest** documents from storage buckets through Flashgate endpoint.
2. **Chunk + embed** each segment (embedding model/service of your choice).
3. **Index** vectors in your search backend (pgvector, OpenSearch, Pinecone, etc.).
4. **Retrieve** top-k chunks at query time.
5. **Generate** final answer via Flashgate AI endpoint with retrieved context.

## Minimal implementation snippets

### 1) Read files from storage endpoint (Python, S3-compatible)

```python
import boto3
from botocore.client import Config

s3 = boto3.client(
    "s3",
    endpoint_url="https://s3-us-east-1-aws.flashback.tech",
    aws_access_key_id="FB_KEY_ID",
    aws_secret_access_key="FB_KEY_SECRET",
    config=Config(signature_version="s3v4")
)

obj = s3.get_object(Bucket="knowledge-bucket", Key="handbook/security.md")
content = obj["Body"].read().decode("utf-8")
```

### 2) Build answer with retrieved chunks (Node.js)

```ts
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: process.env.FB_OPENAI_BASE_URL,
  apiKey: process.env.FB_API_KEY_SECRET
});

export async function answer(question: string, chunks: string[]) {
  const context = chunks.join("\n\n---\n\n");

  const res = await client.chat.completions.create({
    model: "gpt-4.1-mini",
    temperature: 0,
    messages: [
      { role: "system", content: "Answer only using provided context. If unknown, say unknown." },
      { role: "user", content: `Question: ${question}\n\nContext:\n${context}` }
    ]
  });

  return res.choices[0].message.content;
}
```

## Operational recommendations

* Version your chunking strategy and re-index process.
* Add metadata filters (workspace, doc type, language, confidentiality).
* Log retrieval scores and prompt/response latency separately.
* Apply AI policy rules to reduce prompt injection and sensitive output risks.

## Expected outcome

A portable RAG stack where storage and generation are decoupled from any single cloud provider, while still exposed through stable Flashgate APIs.


# Cloud Agent


# Getting Started


# Projects, Sandboxes & Credentials


# Chatting with the Agent


# Templates


# Scheduled Runs


# Runs & History


# Cloud Resources


# Team & Settings


# Start Vibe‑Coding

> This guide is a prompt‑first engineering playbook for **Vibe Coders**, people who use AI to write back‑end code. It explains what the Flashgate platform does, provides guardrails to steer the AI toward correct and secure integrations for both **Storage** and **AI LLM**, and offers ready‑to‑use prompt templates, code scaffolds, and checklists.

## Know the components you are prompting the AI about

| Component                          | Purpose/notes                                                                                                                                                                                 | Key endpoints & examples                                                                                                                                                                                                                                                      |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Bridge Nodes (Storage Gateway)** | Translate standard storage APIs (S3, GCS, Azure Blob) to underlying providers. Endpoint pattern: `https://<api>-<region>-<provider>.flashback.tech`, where `<api>` is `s3`, `gcs`, or `blob`. | <p>Pattern: <code>https\://\<api>-\<region>-\<provider>.flashback.tech</code>.<br>Examples: <code><https://s3-us-east-1-aws.flashback.tech></code>, <code><https://gcs-eu-central-1-gcp.flashback.tech></code>, <code><https://blob-us-east-1-aws.flashback.tech></code>.</p> |
| **Repositories**                   | Aggregate buckets and AI resources; also the scope for API keys and governance.                                                                                                               | Storage stats: `GET https://backend.flashback.tech/repo/stats` (optional `repoId`).                                                                                                                                                                                           |
| **Buckets**                        | Provider buckets/containers registered in Flashgate and attached to repositories.                                                                                                             | Bucket stats: `GET https://backend.flashback.tech/bucket/stats` (optional `bucketId`).                                                                                                                                                                                        |
| **Storage observability**          | Daily/minute storage trends for usage monitoring and incident detection.                                                                                                                      | `GET https://backend.flashback.tech/stats/daily`, `GET https://backend.flashback.tech/stats/minute`.                                                                                                                                                                          |
| **Node telemetry**                 | Bridge-node latency/status for routing and fallback decisions.                                                                                                                                | `GET https://backend.flashback.tech/stats/nodes/minute`.                                                                                                                                                                                                                      |
| **AI LLM configurations**          | Workspace-level provider configs (OpenAI/Gemini/Anthropic/custom) used by repositories through a stable Flashgate gateway.                                                                    | Management endpoints under AI LLM APIs (for example available models/configs), and runtime endpoint like `https://openai-<region>-<provider>.flashback.tech/v1`.                                                                                                              |
| **AI API keys**                    | Repository-scoped keys dedicated to AI requests (separate from storage credentials).                                                                                                          | `POST/GET/PUT/DELETE /repo/{repoId}/ai/apikey...`                                                                                                                                                                                                                             |
| **AI Policy**                      | Governance layer to log/alert/block prompt/response flows by scope (org/workspace/repository).                                                                                                | AI Policy endpoints under AI APIs (`/ai/policy...`).                                                                                                                                                                                                                          |
| **Conversation API**               | Multi-turn chat container with history and context per repository; use when you need persistent conversations instead of single-shot completions.                                             | `POST /conversation`, `GET /conversation`, `POST /conversation/{conversationId}/prompt`, `GET /conversation/{conversationId}/messages`.                                                                                                                                       |
| **AI usage statistics**            | Daily AI metrics across model, key, conversation, and policy dimensions for cost/compliance tracking.                                                                                         | `GET https://backend.flashback.tech/aistats/daily`.                                                                                                                                                                                                                           |

***

## Golden rules (embed these into your AI prompts)

**1 - Use environment variables for secrets**. Never hard‑code credentials. Use variables such as `FB_S3_ENDPOINT`, `FB_KEY_ID`, `FB_KEY_SECRET`, `FB_JWT` and store them in a secret manager.

**2 - Construct the client using the Bridge Node pattern** `https://<api>-<region>-<provider>.flashback.tech` For S3 SDKs, set `forcePathStyle: true` and a dummy region (e.g. `us-east-1`).

**3 - Keep one protocol per process**. Flashgate translates requests across providers, so a single S3 client can talk to GCS or Azure behind the Bridge Node; only use native GCS/Azure libraries if absolutely needed.

**4 - Pull stats for observability**. Use `/repo/stats` to monitor usage across attached buckets, `/bucket/stats` for per‑bucket metrics, `/stats/daily` and `/stats/minute` for aggregated usage trends and `/stats/nodes/minute` for Bridge Node latency.

**5 - Handle quotas and errors gracefully**. Treat HTTP 403/429 or `QUOTA_EXCEEDED` errors as soft signals: pause writes to that bucket or switch to another provider.

**6 - Include retries with exponential backoff**. Use jitter and limit the number of attempts.

***

## Vibe‑Coding for AI LLM (OpenAI‑compatible via Gateway)

Use this section when you want your AI assistant to generate application code for prompts/completions, not only storage operations.

### AI LLM building blocks

* **AI LLM resources**: provider configurations managed in **AI → AI LLM** (provider type, base URL, secret key).
* **Repositories**: attach one or more AI LLM resources to expose a stable OpenAI-compatible endpoint from Flashgate.
* **AI API keys**: repository-scoped keys used as `Authorization: Bearer <key>` for AI calls.
* **Endpoint pattern**: OpenAI-compatible gateway URL, typically like `https://openai-<region>-<provider>.flashback.tech/v1`.

### AI LLM golden rules

**A1 - Use dedicated AI env vars**: `FB_OPENAI_BASE_URL`, `FB_OPENAI_API_KEY`, `FB_MODEL` and optionally `FB_AI_TIMEOUT_MS`.

**A2 - Keep OpenAI contract stable**: code against `/v1/chat/completions` (or OpenAI SDK equivalents) and keep provider switching in Flashgate config, not in application code.

**A3 - Separate keys by workload**: never reuse storage keys for AI calls, and avoid sharing one AI key across multiple services.

**A4 - Build safe fallbacks**: handle transient errors (429/5xx/timeouts) with retries, jitter, and model/provider fallback logic.

**A5 - Add prompt governance checks**: include basic output validation and redact sensitive data before sending prompts where required.

### Quick AI smoke test (cURL)

```bash
curl -sS "$FB_OPENAI_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $FB_OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "'"$FB_MODEL"'",
    "messages": [
      {"role":"system","content":"You are concise."},
      {"role":"user","content":"Return exactly: pong"}
    ],
    "temperature": 0
  }'
```

Expected result: HTTP 200 and a response payload with `choices[0].message.content`.

### Unified AI prompt template for Vibe coders

```txt
Role: Senior backend engineer integrating Flashgate AI Gateway.

Context:
- I provide FB_OPENAI_BASE_URL, FB_OPENAI_API_KEY, FB_MODEL, and optionally FB_AI_TIMEOUT_MS.
- The endpoint is OpenAI-compatible and app code must stay provider-agnostic.
- Use Flashgate AI components correctly: AI LLM config, repository-scoped AI API key, and (if needed) Conversation API.

Requirements:
1) Build a typed AI client wrapper with timeout, retries, jittered exponential backoff, and structured errors.
2) Implement:
   - generateAnswer(input)
   - healthcheck() using a minimal completion call
   - optional conversation helpers using:
     - POST /conversation
     - POST /conversation/{conversationId}/prompt
     - GET /conversation/{conversationId}/messages
3) Handle 429/5xx/timeouts with capped retries and fallback model/provider logic.
4) Read secrets only from env vars and never log prompt secrets, API keys, or raw PII.
5) Add basic governance hooks: redact sensitive input before sending and validate outputs.
6) Add observability hooks for AI usage checks (for example daily stats endpoint).

Output format:
- Production-ready code first.
- Then a concise runbook for key rotation, fallback behavior, and incident response.
```

***

## Vibe‑Coder prompt templates

Use these templates verbatim (with minor changes) to instruct your AI. They embed all the above guardrails.

### General backend integration prompt

> **Role**: Senior backend engineer integrating with Flashgate.\
> **Context**: Flashgate exposes S3/GCS/Blob via Bridge Nodes. The endpoint pattern is `https://<api>-<region>-<provider>.flashback.tech` . I will provide env vars `FB_S3_ENDPOINT`, `FB_KEY_ID`, `FB_KEY_SECRET`, `FB_JWT`, `FB_REPO_ID`. Use path‑style addressing for S3 SDKs. Provide production‑ready code with retries, timeouts and minimal dependencies.\
> **Requirements**:\
> – Configure a client against the Bridge Node.\
> – Implement functions `putObject(bucket, key, bytes)`, `getObject(bucket, key)`, `deleteObject(bucket, key)`.\
> – Add telemetry helpers calling `GET /repo/stats` and `GET /stats/minute` or `GET /stats/nodes/minute`.\
> – Use env vars for secrets.\
> – Include a smoke test.\
> **Docs**: Bridge Node endpoint pattern; repository and performance statistics. Use <https://docs.flashback.tech/> for technical references.\
> **Output**: Code first, then short explanation.

### S3 client scaffold (TypeScript)

> Build `fbS3Client.ts` exporting a cached `S3Client`.\
> – Use `endpoint = process.env.FB_S3_ENDPOINT` (Bridge Node).\
> – Set `forcePathStyle = true` and `region = "us-east-1"`.\
> – Provide functions `putObject`, `getObject` and `deleteObject`.\
> – Use retries with jitter (max 3 attempts) and 30‑second timeouts.

### GCS/Azure variants

> If the project demands native GCS or Azure SDKs, show how to point their `apiEndpoint` or `BlobServiceClient` to the Bridge Node (e.g., `https://gcs-eu-central-1-gcp.flashback.tech` for GCS). Note that Flashgate recommends using S3 SDKs for simplicity since they translate across providers.

### Migration worker prompt

> Implement a migration worker that tries provider‑native copy first (S3 `CopyObject`, GCS `RewriteObject`, Azure `copy_from_url`). If the providers differ, stream via `GetObject` → `PutObject`. Expose a `--dry-run` option, iterate through keys, rate‑limit concurrency and publish counters. Pause or switch if a 403/429 or `QUOTA_EXCEEDED` error occurs.

### Latency and credit‑aware routing prompt

> Fetch `GET /stats/nodes/minute` to find the lowest‑latency Bridge Node. Then fetch `GET /repo/stats` and decide which bucket to use based on credit usage. Provide a function that re‑instantiates the client when the endpoint changes.

***

## Ready‑to‑use scaffolds

### S3 client with caching (Node.js)

```ts
// fbS3Client.ts
import { S3Client } from '@aws-sdk/client-s3';

const cache = new Map<string, S3Client>();

export function s3ClientFor(endpoint: string, accessKeyId: string, secretAccessKey: string) {
  if (!cache.has(endpoint)) {
    cache.set(endpoint, new S3Client({
      endpoint,
      region: 'us-east-1', // unused by Flashgate but required
      credentials: { accessKeyId, secretAccessKey },
      forcePathStyle: true,
    }));
  }
  return cache.get(endpoint)!;
}
```

### Basic operations with retries

```ts
// s3Ops.ts
import { PutObjectCommand, GetObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';
import { s3ClientFor } from './fbS3Client';

const ENDPOINT = process.env.FB_S3_ENDPOINT!;
const KEY_ID = process.env.FB_KEY_ID!;
const KEY_SECRET = process.env.FB_KEY_SECRET!;

async function withRetry<T>(fn: () => Promise<T>, attempts = 3, delay = 200): Promise<T> {
  try {
    return await fn();
  } catch (e) {
    if (attempts <= 1) throw e;
    await new Promise((res) => setTimeout(res, delay + Math.random() * 100));
    return withRetry(fn, attempts - 1, delay * 2);
  }
}

export async function putObject(bucket: string, key: string, body: Buffer) {
  const s3 = s3ClientFor(ENDPOINT, KEY_ID, KEY_SECRET);
  return withRetry(() => s3.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: body })));
}

export async function getObject(bucket: string, key: string) {
  const s3 = s3ClientFor(ENDPOINT, KEY_ID, KEY_SECRET);
  const res = await withRetry(() => s3.send(new GetObjectCommand({ Bucket: bucket, Key: key })));
  return res.Body;
}

export async function deleteObject(bucket: string, key: string) {
  const s3 = s3ClientFor(ENDPOINT, KEY_ID, KEY_SECRET);
  return withRetry(() => s3.send(new DeleteObjectCommand({ Bucket: bucket, Key: key })));
}
```

### Stats helpers (Node.js)

```ts
// fbStats.ts
const BASE = 'https://backend.flashback.tech';
const H = { Accept: 'application/json', Authorization: `Bearer ${process.env.FB_JWT}` };

export async function getRepoStats(repoId?: string) {
  const url = repoId ? `${BASE}/repo/stats?repoId=${repoId}` : `${BASE}/repo/stats`;
  const r = await fetch(url, { headers: H });
  if (!r.ok) throw new Error(`repo stats: ${r.status}`);
  return r.json();
}

export async function getBucketStats(bucketId?: string) {
  const url = bucketId ? `${BASE}/bucket/stats?bucketId=${bucketId}` : `${BASE}/bucket/stats`;
  const r = await fetch(url, { headers: H });
  if (!r.ok) throw new Error(`bucket stats: ${r.status}`);
  return r.json();
}

export async function getDailyStats(startDate?: string, endDate?: string) {
  const qs = [];
  if (startDate) qs.push(`startDate=${startDate}`);
  if (endDate) qs.push(`endDate=${endDate}`);
  const url = `${BASE}/stats/daily${qs.length ? '?' + qs.join('&') : ''}`;
  const r = await fetch(url, { headers: H });
  if (!r.ok) throw new Error(`daily stats: ${r.status}`);
  return r.json();
}

export async function getMinuteStats(repoId?: string, bucketId?: string) {
  const qs: string[] = [];
  if (repoId) qs.push(`repoId=${repoId}`);
  if (bucketId) qs.push(`bucketId=${bucketId}`);
  const url = `${BASE}/stats/minute${qs.length ? '?' + qs.join('&') : ''}`;
  const r = await fetch(url, { headers: H });
  if (!r.ok) throw new Error(`minute stats: ${r.status}`);
  return r.json();
}

export async function getNodeMinuteStats(bucketId?: string) {
  const url = bucketId ? `${BASE}/stats/nodes/minute?bucketId=${bucketId}` : `${BASE}/stats/nodes/minute`;
  const r = await fetch(url, { headers: H });
  if (!r.ok) throw new Error(`node minute stats: ${r.status}`);
  return r.json();
}
```

### Migration helper (S3)

```ts
// migrate.ts
import { CopyObjectCommand, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import { s3ClientFor } from './fbS3Client';
const s3 = s3ClientFor(process.env.FB_S3_ENDPOINT!, process.env.FB_KEY_ID!, process.env.FB_KEY_SECRET!);

// Native provider copy when source and destination share the same provider via the Bridge Node
export async function copyNative(srcBucket: string, srcKey: string, dstBucket: string, dstKey: string) {
  await s3.send(new CopyObjectCommand({ Bucket: dstBucket, Key: dstKey, CopySource: `${srcBucket}/${encodeURIComponent(srcKey)}` }));
}

// Streamed copy for cross‑provider migration
export async function copyStreamed(srcBucket: string, srcKey: string, dstBucket: string, dstKey: string) {
  const obj = await s3.send(new GetObjectCommand({ Bucket: srcBucket, Key: srcKey }));
  await s3.send(new PutObjectCommand({ Bucket: dstBucket, Key: dstKey, Body: obj.Body as any }));
}
```

***

## Prompt cookbook

Use these high‑level prompt recipes to generate code or runbooks via AI.

* **Bootstrap a Flashgate service**: “Create a Node.js service that defines `fbS3Client.ts`, `s3Ops.ts`, `fbStats.ts`, loads env vars, and provides npm scripts `smoke:putgetdel` and `stats:print`. Use the Bridge Node endpoint pattern, set `forcePathStyle = true`, call `/repo/stats` and `/stats/minute`, and include a 60‑second smoke test that writes, reads and deletes an object.”
* **Latency‑aware selector**: “Add a `selectEndpoint()` function that fetches `GET /stats/nodes/minute` and chooses the Bridge Node with the lowest latency. If the selected endpoint changes, rebuild the S3 client and log the change.”
* **Credit‑aware routing**: “Before writing, call `GET /repo/stats`. Compare usage to configured caps for each bucket/provider; choose the first bucket under its cap. On 403/429 or `QUOTA_EXCEEDED`, switch to the next provider.”
* **List available buckets**: “Call `GET /bucket/stats` or `GET /bucket/available` to show attachable bucket IDs. Suggest an operator how to attach them to a repository.”
* **Operator runbook**: “Generate a runbook for rotating repo keys, validating bucket connectivity, executing a dry‑run migration, verifying billing paths, and defining a rollback plan.”

***

## Guardrails to embed in prompts

* Use only the required environment variables for your path: Storage (`FB_S3_ENDPOINT`, `FB_KEY_ID`, `FB_KEY_SECRET`, `FB_JWT`, `FB_REPO_ID`) and/or AI (`FB_OPENAI_BASE_URL`, `FB_OPENAI_API_KEY`, `FB_MODEL`).
* **Never** print secrets or tokens in logs or code.
* Use timeouts (30 seconds) and exponential backoff with jitter.
* Prefer the S3 SDK for storage unless explicitly asked to use GCS or Azure; for AI calls, prefer OpenAI-compatible SDK flows against the Flashgate endpoint.
* When using the S3 SDK, set `forcePathStyle: true` and pass the Bridge endpoint.
* Emit metrics by calling `/stats/minute` and `/stats/nodes/minute` regularly for dashboards and alerts; for AI, also track request latency, token usage, and error rates per model.

***

## Acceptance checklist

* ✅ **Smoke test passes**: the script writes, reads and deletes an object through the Bridge Node.
* ✅ **Secrets stay secret**: all credentials come from env vars and are not logged.
* ✅ **Stats wired**: the code queries `/repo/stats` and `/stats/minute` or `/stats/nodes/minute` and exposes data for dashboards.
* ✅ **Migration tool**: native and streamed copy paths implemented; supports `--dry-run` and concurrency control.
* ✅ **Fallback tested**: on `QUOTA_EXCEEDED` or HTTP 403/429 errors, the system pauses or switches providers and logs the event.
* ✅ **AI smoke test passes**: a `/chat/completions` call via `FB_OPENAI_BASE_URL` succeeds with the repository AI key.
* ✅ **AI isolation respected**: storage and AI keys are separated by workload and never logged.

***

## Troubleshooting playbook

* **403 / 429 or `QUOTA_EXCEEDED`**: Treat this as a soft limit violation. Switch to another bucket/provider or pause writes and alert the operator.
* **High latency**: Query `GET /stats/nodes/minute` to identify a faster Bridge Node; update the endpoint accordingly.
* **Invalid credentials**: Ensure you’re using repository‑scoped access keys for object operations and a Bearer token for management/statistics endpoints.
* **Stats endpoints fail**: Check that your Bearer token (`FB_JWT`) has not expired and that the `Accept: application/json` header is present on requests.
* **AI 401/403**: Confirm you are using a repository AI API key (Bearer), not S3-style key pairs.
* **AI 404 or model errors**: Verify `FB_OPENAI_BASE_URL` includes `/v1` and `FB_MODEL` exists in attached AI LLM providers.

***

## Minimal end‑to‑end example

```ts
// index.ts
import 'dotenv/config';
import { putObject, getObject, deleteObject } from './s3Ops';
import { getRepoStats, getDailyStats, getNodeMinuteStats } from './fbStats';

async function main() {
  const bucket = process.env.FB_BUCKET!;
  await putObject(bucket, 'hello.txt', Buffer.from('hi'));
  const body = await getObject(bucket, 'hello.txt');
  console.log('read:', (await body?.transformToString?.()) || '<stream>');
  await deleteObject(bucket, 'hello.txt');

  const repoStats = await getRepoStats(process.env.FB_REPO_ID);
  console.log('repo stats sample:', JSON.stringify(repoStats).slice(0, 200), '…');

  const daily = await getDailyStats();
  const nodes = await getNodeMinuteStats();
  console.log('daily stats fetched:', !!daily, 'node stats fetched:', !!nodes);
}

main().catch((e) => { console.error(e); process.exit(1); });
```

`.env.example`:

```
FB_S3_ENDPOINT=https://s3-us-east-1-aws.flashback.tech
FB_KEY_ID=REPO_ACCESS_KEY_ID
FB_KEY_SECRET=REPO_SECRET_ACCESS_KEY
FB_JWT=BEARER_TOKEN_FOR_MANAGEMENT
FB_REPO_ID=repo-xxxxxxxx
FB_BUCKET=my-bucket-name
```

This example demonstrates using the Bridge Node endpoint pattern, retrieving repository and node statistics and shows how to write, read and delete an object.

***

## Appendix – Prompt macros

Keep these macros handy for reuse in your Vibe prompts:

* **Flashgate S3 client** – “Create `fbS3Client.ts` that returns a cached S3 client per endpoint; set `forcePathStyle: true`; use env vars; add retries and 30‑second timeout.”
* **Stats wiring** – “Implement `fbStats.ts` with functions calling `/repo/stats`, `/bucket/stats`, `/stats/daily`, `/stats/minute` and `/stats/nodes/minute`; each function returns parsed JSON or throws on failure.”
* **Migration (native → streamed)** – “Write `migrate.ts` that tries provider‑native copy first, then streams via S3 `GetObject`/`PutObject` if providers differ; add `--dry-run`, concurrency control and counters.”
* **Latency selector** – “Add `selectEndpoint()` that reads `/stats/nodes/minute`; if the difference in latency between nodes exceeds 20%, switch to the faster node and rebuild the client.”

By following this guide, you can confidently instruct AI to generate secure, efficient and observability‑friendly integrations with the Flashgate platform, avoiding vendor lock‑in and delivering production‑quality backends on the first try.


# Configure External or Delegated Credentials

Delegated credentials let you authorize Flashgate using provider-native IAM identities and short-lived tokens instead of long-term static secrets.

In practice, this means:

* **Cloud Storage**: grant access via provider IAM roles/policies at bucket/container scope.
* **AI/LLM**: use provider-native identity flows (assumed roles, service accounts, managed identities, token exchanges) and pass endpoint + secret/token to Flashgate's existing AI LLM configuration model.

## When to prefer delegated access

Use delegated access when you want stronger security controls in production:

* avoid long-lived keys where possible,
* centralize permissions in cloud IAM,
* enforce least privilege at narrow scope,
* rotate or expire credentials automatically,
* improve auditability via cloud provider logs.

{% hint style="info" %}
Flashgate configuration still uses product fields documented in [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1) and [Configure a Bucket](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket). Delegated patterns in this section explain how to produce credentials/tokens securely on the provider side.
{% endhint %}

## Delegated Credentials for Cloud Storage

| Provider                                                                                                                         | Description                                                                   |
| -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| [**Amazon Web Services (S3)**](/guides/configure-external-delegated-credentials/configure-external-access-for-aws-s3)            | Configure delegated external access using IAM role assumption patterns.       |
| [**Google Cloud Platform (GCS)**](/guides/configure-external-delegated-credentials/configuring-external-access-for-gcss-buckets) | Configure delegated external access using service-account impersonation.      |
| [**Microsoft Azure (Blob)**](/guides/configure-external-delegated-credentials/configure-external-access-for-azure-blob)          | Configure delegated external access using Entra ID and RBAC role assignments. |

## Delegated Credentials for AI / LLM (Cloud-hosted providers)

| Provider                                                                                                           | Description                                                                              |
| ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
| [**AWS Bedrock**](/guides/configure-external-delegated-credentials/configure-delegated-access-for-aws-bedrock)     | Use IAM role assumption and short-lived credentials for Bedrock invocation flows.        |
| [**GCP Vertex AI**](/guides/configure-external-delegated-credentials/configure-delegated-access-for-gcp-vertex-ai) | Use service accounts and short-lived OAuth tokens (or workload identity) for Vertex AI.  |
| [**Azure OpenAI**](/guides/configure-external-delegated-credentials/configure-delegated-access-for-azure-openai)   | Use Entra ID/RBAC or provider keys, then configure endpoint + secret/token in Flashgate. |

## Security recommendations

* Grant only required actions (read-only, write-only, or specific inference scopes).
* Prefer short-lived tokens over static keys in production.
* Use separate identities for environments (dev, staging, prod).
* Monitor provider audit trails (CloudTrail, Cloud Audit Logs, Azure Activity/Diagnostic logs).
* Review and rotate trust relationships and role assignments regularly.


# Configure S3 external access

## Instructions

Taking as general guide this [AWS article](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html), the step-by-step guide for a user to grant external access is:

{% stepper %}
{% step %}

### Annotate the bucket's ARNs

Go to your S3 console and annotate the resource name (ARN) of the bucket or buckets you want to grant access to. You can find the ARN in the bucket's "Properties" tab.

<figure><img src="/files/5qob1VJrPIFhWrr8uQLg" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Create a new IAM Role

Go to IAM console - Roles and create a new role
{% endstep %}

{% step %}

### Trusted entity type

In the Step 1 of the new role creation, "Select Trusted Entity", we select "Custom Trust policy"

<figure><img src="/files/oHQzSXw7gNZ3kPslIJhC" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Set custom trust policy

In the custom trust policy section, we enter the Flashgate network AWS's trusted principal ARN descriptor.

* The AWS Principal must be exactly the same string as indicated below "**arn:aws:iam::314146316322:user/flashgate**"
* The "Action" must be "**sts:AssumeRole**"
* The ExternalId can be one of our choice as long as it contains valid characters.

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::314146316322:user/flashgate"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "sts:ExternalId": "flashgate-service-3e1f7bd5"
                }
            }
        }
    ]
}
```

{% hint style="info" %}
In the "sts:ExternalId" parameter you can write whatever string ID you want, but you have to keep it annotated because it will be necessary when [configuring the Storage Bucket](broken://pages/cEHgDv7NGBquDGHeLyQ4#storage-type-s3) in the Platform interface.
{% endhint %}
{% endstep %}

{% step %}

### Permission Policies

In Step 2 of the new role creation, Permissions Policies, we are going to need a custom inline policy. If we don't see any option to add it (normally we only see the standard AWS policies), we can leave this blank for later and skip on to the next step.
{% endstep %}

{% step %}

### Enter role name and description

In the final Step 3 of the new role creation process, we give the Role an easily identifiable name and description. We can optionally add one or more tags if we want.
{% endstep %}

{% step %}

### Edit the new role to apply the custom inline policy

After creating the new role, we are going to edit it to apply the custom inline security policy:

* We go to Permissions tab, and in the "Add permissions" menu, we select "Create Inline Policy"

<figure><img src="/files/5pFW9OyuAgOfgYS3LeZV" alt=""><figcaption></figcaption></figure>

* We paste the following JSON
  * If we are granting access to a single bucket called "mybucket1":

```
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"s3:ListBucket"
			],
			"Resource": "arn:aws:s3:::mybucket1"
		},
		{
			"Effect": "Allow",
			"Action": [
				"s3:GetObject",
				"s3:PutObject",
				"s3:DeleteObject"
			],
			"Resource": "arn:aws:s3:::mybucket1/*"
		}
	]
}
```

* If we are granting access to more than one bucket, then we have to indicate the "Resource" field as an array with the list of bucket ARNs and bucket contents (mybucket/\*):

```
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"s3:ListBucket"
			],
			"Resource": [
				"arn:aws:s3:::mybucket1",
				"arn:aws:s3:::mybucket2",
				...
				"arn:aws:s3:::mybucketN",
			]
		},
		{
			"Effect": "Allow",
			"Action": [
				"s3:GetObject",
				"s3:PutObject",
				"s3:DeleteObject"
			],
			"Resource": [
				"arn:aws:s3:::mybucket1/*",
				"arn:aws:s3:::mybucket2/*",
				...
				"arn:aws:s3:::mybucketN/*",
			]
		}
	]
}
```

{% hint style="info" %}
Adapt the delegated role custom policy to your requirements. For example, if you don't want Flashgate Network to delete objects from the bucket, remove the "s3:DeleteObject" permission.

The same applies in case you want to grant more Actions permissions to the user.

A list of the currently supported S3 actions in Flashgate Network
{% endhint %}
{% endstep %}

{% step %}

### Setting up the maximum session duration to 1 hour

We set up the maximum session duration to 1 hour by editing the Role Summary properties (button "Edit" to the right):

<figure><img src="/files/7L2HYELMIZYCpe9mtUS8" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/B5AzC58sfMqgG9qs729M" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Flashgate Network nodes will renew the external access credentials every 1h by default, so indicating a duration higher than 1 hour will make no real impact.
{% endhint %}

{% hint style="danger" %}
**Important:** Indicating a custom period of less than 1h can cause premature session termination and connectivity problems in the nodes.
{% endhint %}

If you require nodes to hold temporary sessions of less than 1h for compliance or other reasons, please contact Flashgate Support.
{% endstep %}
{% endstepper %}


# Configuring GCS' external access

## Instructions

Taking as general guide [this article](https://cloud.google.com/iam/docs/manage-access-service-accounts), we enumerate the steps to set up external delegated access to the Flashgate service account:

{% stepper %}
{% step %}

### Create a service account

In Google Cloud Console, select the project where your bucket resources are, and create a service account on "IAM & Admin - Service Accounts - Create service account".

Enter an easily recognizable name and description. For our example purposes we created one called "Flashgate Storage TEST".
{% endstep %}

{% step %}

### Grant the service account access to the bucket resources

If for example you want the service account to have full access in the project on in a specific bucket, you can grant it the "Storage admin" and "Storage Object admin" roles.

If you want more specific/granular access, you will have to create specific access roles and apply them to the service account at the required scope.
{% endstep %}

{% step %}

### Add impersionation roles to Flashgate service account

Go to the newly created service account, and in "Permissions" tab, press button below "+ Grant Access"

<figure><img src="/files/UaRVPMYLS33y1PHmNl4H" alt=""><figcaption></figcaption></figure>

Then a modal opens to the right and we have to indicate the following:

* In Principals, we enter "**<flashgate-network@flashgate-network.iam.gserviceaccount.com>**"
* In "Roles", we add "**Service Account Token Creator**" y "**Service Account User**"

<figure><img src="/files/nOAjF5AwH3syv4eLo5dD" alt=""><figcaption></figcaption></figure>

Then we Save.
{% endstep %}
{% endstepper %}

Now, when configuring the GCS bucket, we will indicate our service account principal as client email, and will leave the "Private Key" to empty. This will signal Flashgate nodes that the access to the bucket is delegated to Flashgate's service account.


# Configure Azure Blob delegated access

## What you will achieve

You will configure Azure Blob access for Flashgate using **Microsoft Entra ID + RBAC** so you can avoid long-lived storage account keys where possible.

## Azure delegated access model (practical view)

For delegated access, assign data-plane RBAC roles to the Flashgate Azure identity (guest user or service principal) at the right scope:

* **Storage account scope** when access should apply to many containers.
* **Container scope** when you want narrower least-privilege access.

{% hint style="info" %}
Use Entra ID + RBAC where possible. Account keys are broad, long-lived secrets and should be treated as fallback.
{% endhint %}

## Prerequisites

* An Azure subscription.
* A storage account and target container.
* Permissions to assign RBAC roles (for example Owner or User Access Administrator at the target scope).
* The Flashgate Azure identity identifier (guest user object ID or service principal app/object ID).
  * If you do not have it, obtain it from Flashgate support or from the Flashgate UI/documentation available in your organization.

## Step-by-step (Azure Portal)

{% stepper %}
{% step %}

#### Identify the target scope

Choose where to assign permissions:

* **Storage account**: broader scope, easier operations.
* **Container**: tighter least-privilege boundary (recommended when only specific containers are needed).

In Azure Portal, open your Storage Account, then either:

* stay at storage account level, or
* open **Data storage → Containers →&#x20;*****your-container*** for container-level scope.
  {% endstep %}

{% step %}

#### Add role assignment for Flashgate identity

1. Open **Access control (IAM)** on the selected scope.
2. Click **Add → Add role assignment**.
3. Select a minimum role based on required operations:
   * **Storage Blob Data Reader** (read-only)
   * **Storage Blob Data Contributor** (read/write/delete for blob data)
4. Assign access to the Flashgate Azure identity (guest user or service principal).
5. Save the assignment.

{% hint style="warning" %}
Use the smallest role that satisfies your workflow. Avoid account-wide roles if container-level access is enough.
{% endhint %}
{% endstep %}

{% step %}

#### (Optional) Review network restrictions

If your storage account uses firewalls, private endpoints, or restricted networks, ensure Flashgate traffic can reach Azure Blob endpoints.

Delegated IAM permissions alone do not bypass network controls.
{% endstep %}

{% step %}

#### Configure the bucket in Flashgate

In Flashgate, follow [Configure a Bucket](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket) and select:

* **Storage Type**: `Azure Blob`
* **Storage Account**: your Azure storage account name
* **Container**: your target container
* **Access Key**: may be left blank for delegated guest access when supported by your product flow (as documented in the bucket configuration guide)
  {% endstep %}

{% step %}

#### Validate access

After saving, run a basic repository validation:

* attach the bucket to a repository,
* perform a simple read/write test according to your role,
* verify expected success/failure behavior.

If your workspace has a dedicated validation flow, use that flow first.
{% endstep %}
{% endstepper %}

## Troubleshooting

* **RBAC changes seem ignored**: role propagation can take several minutes.
* **Wrong scope assigned**: confirm the role is assigned at the correct container or storage-account scope.
* **Role mismatch**: ensure you granted a **data-plane** blob role (for example Storage Blob Data Reader/Contributor), not only management-plane permissions.
* **Guest account restrictions**: some tenants restrict B2B/guest permissions; verify tenant policies for external principals.


# Configure delegated access for AWS Bedrock

## Overview

For AWS Bedrock, delegated access usually means using IAM role assumption (STS) and short-lived credentials instead of distributing long-lived AWS keys.

Bedrock APIs are generally authenticated with **SigV4** signing. Flashgate's AI LLM configuration accepts provider endpoint + secret/token fields, so production integrations often use a controlled credential flow or a signing gateway.

## When to use this

* Production workloads with strict key management requirements.
* Teams using centralized IAM and short credential lifetime.
* Multi-team environments where external access must be auditable and revocable.

## Prerequisites

* AWS account with Bedrock enabled in your target region.
* Permissions to create/update IAM roles and trust policies.
* Defined list of models/actions required by your workload.
* Flashgate AI LLM setup path: [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1).

## Step-by-step (provider side)

{% stepper %}
{% step %}

### Create an IAM role with least privilege

Create a role for delegated Bedrock access and attach only required actions, for example:

* `bedrock:InvokeModel`
* `bedrock:InvokeModelWithResponseStream` (if streaming is needed)
* optional model discovery permissions only if your flow requires them.

Scope permissions to required model ARNs/regions whenever possible.
{% endstep %}

{% step %}

### Configure trust policy with STS AssumeRole + External ID

Use a third-party access trust policy pattern (`sts:AssumeRole`) and require an External ID condition.

This reduces confused-deputy risk and keeps delegated access explicit and auditable.
{% endstep %}

{% step %}

### Choose an integration pattern for Flashgate

Because Bedrock requests are SigV4-signed, common patterns are:

1. **Signing gateway/proxy pattern (recommended for many setups)** Run an internal service that:
   * assumes the IAM role,
   * signs Bedrock requests with SigV4,
   * exposes a stable endpoint that Flashgate can call.
2. **Direct configuration pattern (only if supported in your environment)** If your Flashgate environment supports direct Bedrock endpoint + secret/token flow, configure only documented fields and validate.

{% hint style="info" %}
If direct Bedrock auth behavior is not explicitly documented in your environment, treat it as an integration pattern and validate with a non-production model first.
{% endhint %}
{% endstep %}
{% endstepper %}

## Configure in Flashgate

Use [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1) with the existing model:

* Select the appropriate **AI LLM Type** for your provider/integration.
* Set **API Endpoint** to your provider endpoint or signing proxy endpoint.
* Set **API Secret** to the credential/token expected by that endpoint.
* Use **API Key** only if your endpoint requires it.

Do not add undocumented fields; map provider-side delegated credentials to Flashgate's existing endpoint + secret/token inputs.


# Configure delegated access for GCP Vertex AI

## Overview

For Vertex AI, delegated access is typically implemented with a Google service account and short-lived OAuth access tokens generated through secure identity flows.

In production, prefer Workload Identity Federation or managed identity paths over long-lived JSON key files.

## When to use this

* Production systems where static service-account keys are discouraged.
* Centralized IAM/security operations with scoped permissions.
* Environments requiring frequent credential rotation and strong audit trails.

## Prerequisites

* GCP project with Vertex AI enabled.
* Permissions to create/manage service accounts and IAM roles.
* A service account dedicated to Flashgate AI provider access.
* Flashgate AI LLM setup path: [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1).

## Step-by-step (provider side)

{% stepper %}
{% step %}

### Create a service account with least privilege

Create a service account for Vertex AI calls and assign only required permissions.

Use minimum roles required for your use case (for example, prediction/invocation capabilities instead of broad project admin roles).
{% endstep %}

{% step %}

### Prefer short-lived credentials

Use Workload Identity / token exchange flows to obtain short-lived OAuth access tokens.

Avoid storing long-lived JSON private keys in production when possible.
{% endstep %}

{% step %}

### Generate and refresh access tokens

Implement a secure token refresh mechanism (for example in a trusted backend service) that obtains fresh OAuth access tokens before expiry.

If your architecture needs a stable upstream interface, expose a small proxy that handles token acquisition and forwards requests to Vertex AI.
{% endstep %}
{% endstepper %}

## Configure in Flashgate

Use [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1) with existing fields:

* Choose the appropriate **AI LLM Type** for your Vertex integration.
* Set **API Endpoint** to Vertex AI endpoint (or your proxy endpoint).
* Set **API Secret** to the token/credential expected by that endpoint.
* Set **API Key** only if your integration endpoint requires an additional key.

{% hint style="info" %}
If your provider flow cannot be mapped directly to endpoint + secret/token, place the identity logic in a controlled proxy and configure Flashgate to call that proxy.
{% endhint %}


# Configure delegated access for Azure OpenAI

## Overview

For Azure OpenAI, delegated access can use Microsoft Entra ID identities (managed identity or service principal) with RBAC, or Azure OpenAI keys where required.

The delegated approach focuses on identity-based authorization and short-lived tokens instead of broad static secrets.

## When to use this

* Production workloads under centralized identity governance.
* Organizations already using Entra ID, managed identities, and RBAC.
* Teams that need auditable, revocable, least-privilege AI access.

## Prerequisites

* Azure subscription with Azure OpenAI resource.
* Permission to manage role assignments and application identities.
* Service principal or managed identity designated for AI access.
* Flashgate AI LLM setup path: [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1).

## Step-by-step (provider side)

{% stepper %}
{% step %}

#### Prepare identity and RBAC access

Create/select a managed identity or service principal and grant only required access on the Azure OpenAI resource scope.

Use least privilege and limit scope to the required resource(s).
{% endstep %}

{% step %}

#### Choose token-based or key-based provider auth

Preferred pattern:

* Use Entra ID token flow for short-lived access tokens.

Fallback pattern (if required by your integration constraints):

* Use Azure OpenAI key-based authentication with strict secret management.
  {% endstep %}

{% step %}

#### Implement token/key delivery pattern

If using Entra ID tokens, ensure your backend refreshes tokens before expiration.

If needed, place a controlled proxy between Flashgate and Azure OpenAI so the proxy handles token management while Flashgate uses stable endpoint + secret/token inputs.
{% endstep %}
{% endstepper %}

## Configure in Flashgate

Use [Configure an AI LLM](/guides/setup-the-cloud-and-ai-gateway/start-with-cloud-storage/create-a-bucket-1) and map provider outputs to existing fields:

* Select the correct **AI LLM Type** for your Azure/OpenAI-compatible flow.
* Set **API Endpoint** to Azure OpenAI endpoint (or your proxy endpoint).
* Set **API Secret** to the token/secret expected by that endpoint.
* Set **API Key** only when your endpoint requires it.

Do not assume additional product toggles or delegated-mode fields beyond documented UI fields.


# Platform API Reference

## Flashgate API v0.0.60 <a href="#flashgate-api" id="flashgate-api"></a>

> Find categories, code samples, example requests and responses. Select a language for code samples of API calls in the tabs or the mobile navigation menu.

Flashgate provides a unified API to seamlessly manage cloud storage across diverse platforms, including:

* **Major providers**: AWS S3, Google Cloud Storage (GCS), Azure Blob Storage (more soon)
* **Decentralized and compatible services**: StorJ, Akave, and other S3/GCS-compatible systems

Through the API, developers and system administrators can:

* Provision and manage storage buckets
* Configure repositories with automated backup and mirroring
* Monitor performance and usage metrics in real time
* Control access securely with API keys
* Gain visibility into storage health and availability

***

## API Reference Index

{% hint style="warning" %}
Check the [additional information](#additional-information) for a full understanding of your management options in this section.
{% endhint %}

This documentation is structured into functional categories for ease of navigation:

<table><thead><tr><th width="179.39996337890625">Category</th><th>Description</th></tr></thead><tbody><tr><td><a href="/pages/ZC92e3V5jjFhzwsIZUOk">Authentication</a></td><td><p>Have your authentication needs with Flashgate’s versatile Auth API:</p><ul><li>Initiate OAuth flows with Google or GitHub, or authenticate via email/password in a single call.</li><li>Exchange codes or credentials to receive JWT access and refresh tokens.</li><li>Refresh or revoke tokens to maintain session continuity and security.</li></ul></td></tr><tr><td><a href="/pages/3R1619tSZLfHMHfagYp6">User Account</a></td><td><p>Cover your user account.</p><ul><li>Secure API access using JWT tokens for user sessions or OAuth2 for delegated identity management.</li><li>Access Flashgate environments via dedicated endpoints for development and production use.</li></ul></td></tr><tr><td><a href="/pages/uuUmAn0zUgsL0J4DApZ6">MFA (multi-factor authentication)</a></td><td><p>Cover your multi-factor authentication (MFA) needs with Flashgate’s secure, flexible MFA API:</p><ul><li>Initiate MFA enrollment, deliver QR codes or challenges, verify setup, and enable methods in just a few calls.</li><li>After primary login, trigger MFA challenges, accept TOTP codes (Google Authenticator), one-time Magic Links, or WebAuthn passkeys, and grant full access upon success.</li><li>List, add or remove methods, set your primary MFA, and reset configurations to maintain control.</li></ul></td></tr><tr><td><a href="/pages/yGwOZ7GTksj9eTGqy2UD">Organization</a></td><td><p>Parametrize your organization management needs with Flashgate’s Org API:</p><ul><li>Create, update, or delete organizations and configure settings in a single call.</li><li>Add, remove, or list organization users and assign roles programmatically.</li><li>Have access to role-based access control (USER, BILLING, WORKSPACES, ADMINISTRATOR, OWNER) for every operation.</li></ul></td></tr><tr><td><a href="/pages/6E2hCWmL8JMT1VXIa7uX">Workspace</a></td><td><p>Manage your workspace management needs with Flashgate’s Workspace API:</p><ul><li>Create, list, update, and delete workspaces to group users and resources within your organization.</li><li>Assign READ, WRITE, and ADMIN permissions; Organization Owners, Administrators, and Workspace Managers can create workspaces, while Workspace Admins manage users, settings, and deletion (if empty).</li></ul></td></tr><tr><td><a href="/pages/DwvlmbN22lQ7RbjbTSPk">Repository</a></td><td><p>Set up and control repositories used for backup, mirroring, and synchronization workflows.</p><ul><li>Link multiple buckets under a logical repository</li><li>Define sync schedules, mirror configurations, and data redundancy policies</li><li>Monitor repository health and ensure consistency across providers</li></ul></td></tr><tr><td><a href="/pages/HuRTrrBKR4cG81p3gGOY">Cloud Storage</a></td><td><p>Create and manage storage buckets across different providers.</p><ul><li>Supports unified creation/configuration for AWS S3, GCP Google Cloud Storage, Microsoft Azure Blob, and S3/GCS-compatible services</li><li>Enables provider-specific configuration such as regions, replication settings, and lifecycle rules</li><li>Manage permissions, encryption, and storage classes</li></ul></td></tr><tr><td>↳ <a href="/pages/Akx2ZCRINLZ8Z5SovHel">Bucket Management</a></td><td>Manage storage buckets across AWS, GCS, Azure, and S3/GCS-compatible providers: create, list, update, delete (soft delete), validate connectivity, and retrieve usage/performance stats.</td></tr><tr><td>↳ <a href="/pages/T4lIisZTXikF2Jz2eSjP">Repo Storage API Keys</a></td><td><p>Manage access credentials for secure interaction with the Flashgate API.</p><ul><li>Generate API keys with scoped permissions with repositories (read, write, admin)</li><li>Enable or disable keys without deleting them</li><li>Use keys for fine-grained control over repository-level access</li></ul></td></tr><tr><td>↳ <a href="/pages/1UucJUQDNTPIGmRjPnLQ">Storage Bridge Node Registration</a></td><td><p>Use for your node registration and organization key management needs with Flashgate’s Node API:</p><ul><li>Register bridge nodes via cryptographic signatures—no auth needed—and manage node metadata, health checks, and status in a few calls.</li></ul></td></tr><tr><td>↳ <a href="/pages/z3MmWW7AlQnsk9LpbVOF">Bridge Node Status</a></td><td><p>Access details about Flashgate’s node infrastructure and availability.</p><ul><li>View metadata and health of nodes deployed across AWS, GCP, Azure, and other locations</li></ul></td></tr><tr><td><a href="/pages/G1OSdpgox5J8yZ9SsAtG">AI</a></td><td>Configure AI providers and enforce AI governance policies for workspaces and repositories, centralizing credentials, usage, and compliance across AI usage.</td></tr><tr><td>↳ <a href="/pages/FLyG0szOzAaXnic0aaLI">AI LLMs</a></td><td>Configure and manage connections to external AI providers, validate credentials, and make models available to workspaces and repositories.</td></tr><tr><td>↳ <a href="/pages/NZ1W2AkWRO8JCMrihjvb">AI Policy</a></td><td>Define and enforce natural-language governance rules with risk levels and actions (log, alert, block), scoped at organization, workspace, or repository level.</td></tr><tr><td>↳ <a href="/pages/K2wga7iZX2CN3AOiZQ9J">AI API Keys</a></td><td>Create and manage scoped API keys that applications use to call AI endpoints, controlling which LLM configurations and repositories they can access and how much usage they are allowed.</td></tr><tr><td><a href="/pages/Kmny8Fw5g83OvrgWOMWi">Conversation (Chat)</a></td><td><p>Create and manage AI conversations tied to repositories.</p><ul><li>Send prompts and retrieve messages for multi-turn interactions</li><li>Track token usage and apply AI governance policies during interactions</li></ul></td></tr><tr><td><a href="/pages/VYvd1v9iOHG3PtssGMf9">Performance Statistics</a></td><td><p>Fetch detailed usage and performance metrics.</p><ul><li>Retrieve daily summaries or minute-level usage data</li><li>Metrics include: storage volume, read/write operations, latency, and error rates</li></ul></td></tr><tr><td><a href="/pages/gOSdnvttyGqajuFoKYng">Credits</a></td><td><p>Inspect and manage your organization’s credit balance and credit usage.</p><ul><li>Review balances, transactions, packs, and consumption rates</li><li>Start Stripe checkouts for credit pack purchases</li></ul></td></tr><tr><td><a href="/pages/1cwKCrhyINVy58RzCv4e">Subscriptions</a></td><td><p>Manage subscription plans, checkout, and billing portal flows.</p><ul><li>List plans and periods, create Stripe checkout sessions, and confirm payment status</li><li>View current subscription state, payments history, and cancel subscriptions</li></ul></td></tr><tr><td><a href="/pages/tliGMZY1jdpVPLcuhjBJ">Additional Services</a></td><td><p>Utility endpoints and auxiliary services.</p><ul><li>Includes feedback submission (email integration)</li><li>Experimental or non-core service features may appear here</li></ul><p>Check the real-time and historical status of Flashgate services.</p><ul><li>Includes uptime records, incident history, and component-level status</li><li>Authenticated endpoints to verify service identity and readiness</li></ul></td></tr><tr><td><a href="/pages/TRBRIrdq3NHz8ZnHkb0q">Device/Session management</a></td><td><p>Manage your device and session management needs with Flashgate’s Device &#x26; Session API:</p><ul><li>View and manage registered devices and control trust levels in a few calls.</li><li>Monitor active sessions across devices and revoke sessions for security purposes.</li></ul></td></tr><tr><td><a href="/pages/9lJPexD1ON19rMlCLrHG">Settings</a></td><td><p>Configure your settings management needs with Flashgate’s Settings API:</p><ul><li>Retrieve, fully replace, partially update, or delete user and organization preferences in just a few calls.</li><li>Use dedicated endpoints for User Settings and Organization Settings.</li></ul></td></tr></tbody></table>

***

## HTTP Bearer Authentication

Flashgate uses **HTTP Bearer Authentication** with **JWT (JSON Web Tokens)**.\
To authenticate your requests, first obtain a JWT from the appropriate login or OAuth endpoint.\
Then include it in the `Authorization` header of every API call like this:

```json
Authorization: Bearer <your-jwt-token>
```

This token confirms your identity and grants access to protected resources. Be sure to keep it secure.

***

## Additional Information

#### Authentication

This API supports three authentication mechanisms:

1. **Internal Authentication** - Email/password based authentication with JWT tokens
2. **Google OAuth** - Google OAuth 2.0 authentication
3. **GitHub OAuth** - GitHub OAuth 2.0 authentication

#### Account Validation

* New user registrations require email verification
* Verification tokens expire after 24 hours
* Write operations (create/update/delete) are blocked until email verification is complete
* Read operations remain available for unverified accounts

#### Base URL

* Production: <https://backend.flashback.tech>
* Development: provided by Flashgate team upon request.
* Email: [Flashgate Support](mailto:support@flashback.tech) License: [Proprietary](https://flashback.tech/license)

#### Rate Limits

* 100 requests per minute per IP
* 1000 requests per hour per user

#### File Upload Limits

* **Feedback emails**: Maximum 10MB per file, 25MB total
* **Storage operations**: 100MB per file (handled by external nodes)

#### Quota Management

The platform uses a subscription-based quota system. When quotas are exceeded:

* Repository operations are automatically disabled
* Read operations remain available
* Quotas reset based on your subscription period

#### Error Handling

All endpoints return consistent error responses with:

* `success`: boolean indicating operation status
* `message`: human-readable error description
* `error_code`: machine-readable error code (when applicable)

#### Common error codes

* `QUOTA_EXCEEDED`: Organization has reached its limits
* `NAME_ALREADY_USED`: Resource name already exists
* `NOT_FOUND`: Requested resource doesn't exist
* `VALIDATION_ERROR`: Request data is invalid

***

## Support

For questions or issues, use the [feedback system APIs](/support-reference/platform-api-reference/other-apis), in your Flashgate platform interface or contact [Flashgate Support](mailto:support@flashback.tech).


# Authentication

The table below provides a comprehensive overview of the Flashgate API authentication endpoints, grouped by functional area. Each section lists the available HTTP functions along with a concise description of their purpose, helping developers understand how to authenticate users, manage OAuth flows, and control access tokens.

{% hint style="info" %}
Authentication is required for most API operations. The Flashgate platform supports multiple authentication methods including OAuth providers and traditional username/password authentication.
{% endhint %}

## Token Management API Calls

<table><thead><tr><th width="247.4000244140625">Method</th><th>API Reference</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:green;"><code>GET</code></mark><code>/token</code></td><td><a href="/pages/9hVUSGDfoanSttMqZ2Es"><strong>get__token</strong></a></td><td>List all active refresh tokens for the user.</td></tr><tr><td><mark style="color:red;"><code>DELETE</code></mark><code>/token/{tokenId}</code></td><td><a href="/pages/uGgNTnNQg6wtH9cKCxoq"><strong>delete__token_{tokenId}</strong></a></td><td>Revoke a specific refresh token.</td></tr></tbody></table>

## OAuth Authentication API Calls

<table><thead><tr><th width="247.4000244140625">Method</th><th>API Reference</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/auth/google</code></td><td><a href="/pages/9op6xMR4agPYPJgIVRT5"><strong>post__auth_google</strong></a></td><td>Authenticate user using a Google OAuth access token.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/auth/github</code></td><td><a href="/pages/3LFtgRjM34Evvcm4co72"><strong>post__auth_github</strong></a></td><td>Authenticate user using a GitHub OAuth code.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/auth/github/refresh</code></td><td><a href="/pages/XvRdvIdR1bs34PBxvOmm"><strong>post__auth_github_refresh</strong></a></td><td>Refresh an expired GitHub access token.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/auth/google/refresh</code></td><td><a href="/pages/H2TnKIrYZDNqPYnI5FCx"><strong>post__auth_google_refresh</strong></a></td><td>Refresh an expired Google access token.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/auth/google/exchange</code></td><td><a href="/pages/xlYrK40BZUV5Js169XOJ"><strong>post__auth_google_exchange</strong></a></td><td>Exchange Google OAuth code for an access token.</td></tr></tbody></table>

## Authentication Flow Overview

### OAuth Authentication

The Flashgate platform supports OAuth 2.0 authentication with popular providers:

* **Google OAuth**: Complete OAuth flow including code exchange and token refresh
* **GitHub OAuth**: GitHub-specific OAuth implementation with refresh capabilities

### Traditional Authentication

For applications that prefer traditional authentication:

* **User Registration**: Create new user accounts with email verification
* **User Login**: Authenticate with email/password credentials
* **Token Refresh**: Maintain session continuity with refresh tokens

### Token Management

Secure token lifecycle management:

* **Token Listing**: View all active refresh tokens for the current user
* **Token Revocation**: Securely revoke specific refresh tokens when needed

{% hint style="warning" %}
**Security Note**: Always use HTTPS in production environments and store refresh tokens securely. Never expose access tokens in client-side code or logs.
{% endhint %}


# get\_\_token

`GET /token`

*List User Tokens*

Get all refresh tokens for the authenticated user

#### TypeScript Client Library

```typescript
  public getTokens = async (): Promise<{ success: boolean; tokens: any[] }> => {
    return this.makeRequest<{ success: boolean; tokens: any[] }>('token', 'GET', null);
  };
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X GET https://backend.flashback.tech/token \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
GET https://backend.flashback.tech/token HTTP/1.1
Host: localhost:3000
Accept: application/json
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/token',
{
  method: 'GET',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.get 'https://backend.flashback.tech/token',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.get('https://backend.flashback.tech/token', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://backend.flashback.tech/token', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/token");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://backend.flashback.tech/token", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Example responses

> 200 Response

```json
{
  "success": true,
  "tokens": [
    {}
  ]
}
```

**Responses**

| Status | Meaning                                                 | Description    | Schema |
| ------ | ------------------------------------------------------- | -------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | List of tokens | Inline |

**Response Schema**

Status Code **200**

| Name      | Type      | Required | Restrictions | Description |
| --------- | --------- | -------- | ------------ | ----------- |
| » success | boolean   | false    | none         | none        |
| » tokens  | \[object] | false    | none         | none        |

To perform this operation, you must be authenticated by means of one of the following methods: BearerAuth


# delete\_\_token\_{tokenId}

`DELETE /token/{tokenId}`

*Revoke Token*

Revoke a specific refresh token

#### TypeScript Client Library

```typescript
  public revokeToken = async (tokenId: string): Promise<{ success: boolean }> => {
    return this.makeRequest<{ success: boolean }>(`token/${tokenId}`, 'DELETE', null);
  };
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X DELETE https://backend.flashback.tech/token/{tokenId} \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
DELETE https://backend.flashback.tech/token/{tokenId} HTTP/1.1
Host: localhost:3000
Accept: application/json
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/token/{tokenId}',
{
  method: 'DELETE',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.delete 'https://backend.flashback.tech/token/{tokenId}',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.delete('https://backend.flashback.tech/token/{tokenId}', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://backend.flashback.tech/token/{tokenId}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/token/{tokenId}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://backend.flashback.tech/token/{tokenId}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

**Parameters**

| Name    | In   | Type   | Required | Description |
| ------- | ---- | ------ | -------- | ----------- |
| tokenId | path | string | true     | none        |

> Example responses

> 200 Response

```json
{
  "success": true
}
```

**Responses**

| Status | Meaning                                                 | Description                | Schema |
| ------ | ------------------------------------------------------- | -------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Token revoked successfully | Inline |

**Response Schema**

Status Code **200**

| Name      | Type    | Required | Restrictions | Description |
| --------- | ------- | -------- | ------------ | ----------- |
| » success | boolean | false    | none         | none        |


# post\_\_auth\_google

`POST /auth/google`

*Google OAuth Authentication*

Authenticate user with Google OAuth access token.

This endpoint validates a Google OAuth access token and creates or updates the user account. The system automatically:

* Creates an organization based on the email domain
* Assigns appropriate subscription based on account type
* Handles both personal (gmail.com) and business accounts

**Account Types:**

* **Personal**: gmail.com addresses create personal accounts
* **Business**: Other domains create business accounts with organization name derived from domain

**Requirements:**

* Valid Google OAuth access token
* Token must be obtained through proper OAuth flow

#### TypeScript Client Library

```typescript
private authenticateGoogle = async (data: AuthTypes.GoogleLoginRequest): Promise<any> => {
  this.setAuthToken(data.token);
  return this.makeRequest<any>('auth/google', 'POST', data);
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/auth/google \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/auth/google HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "token": "ya29.a0AfH6SMC..."
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/auth/google',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/auth/google',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/auth/google', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://backend.flashback.tech/auth/google', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/auth/google");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/auth/google", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Body parameter

```json
{
  "token": "ya29.a0AfH6SMC..."
}
```

**Parameters**

| Name    | In   | Type   | Required | Description                                           |
| ------- | ---- | ------ | -------- | ----------------------------------------------------- |
| body    | body | object | true     | none                                                  |
| » token | body | string | true     | Google OAuth access token from client-side OAuth flow |

> Example responses

> 200 Response

```json
{
  "success": true,
  "message": "User logged in",
  "refreshToken": "string",
  "token": "string"
}
```

**Responses**

| Status | Meaning                                                 | Description               | Schema |
| ------ | ------------------------------------------------------- | ------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Authentication successful | Inline |

**Response Schema**

Status Code **200**

| Name           | Type    | Required | Restrictions | Description                                   |
| -------------- | ------- | -------- | ------------ | --------------------------------------------- |
| » success      | boolean | false    | none         | none                                          |
| » message      | string  | false    | none         | none                                          |
| » refreshToken | string  | false    | none         | JWT refresh token for future authentication   |
| » token        | string  | false    | none         | Original Google access token (for client use) |

To perform this operation, you must be authenticated by means of one of the following methods: BearerAuth


# post\_\_auth\_github

`POST /auth/github`

*GitHub OAuth Authentication*

Authenticate user with GitHub OAuth authorization code.

This endpoint handles GitHub OAuth authentication, similar to Google OAuth but using GitHub's OAuth flow. The system creates or updates user accounts based on GitHub profile information.

**GitHub OAuth Flow:**

1. Redirect user to GitHub OAuth consent screen
2. User authorizes your application
3. GitHub returns authorization code
4. Call this endpoint with the code
5. Receive authentication state with user info and tokens

**Account Creation:**

* Organization name derived from GitHub username or company
* Email from GitHub profile
* Profile image from GitHub avatar

#### TypeScript Client Library

```typescript
private authenticateGithub = async (data: AuthTypes.GithubLoginRequest): Promise<any> => {
  this.setAuthToken(data.code);
  return this.makeRequest<any>('auth/github', 'POST', data);
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/auth/github \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/auth/github HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "code": "abc123def456..."
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/auth/github',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/auth/github',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/auth/github', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://backend.flashback.tech/auth/github', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/auth/github");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/auth/github", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Body parameter

```json
{
  "code": "abc123def456..."
}
```

**Parameters**

| Name   | In   | Type   | Required | Description                                         |
| ------ | ---- | ------ | -------- | --------------------------------------------------- |
| body   | body | object | true     | none                                                |
| » code | body | string | true     | GitHub authorization code from OAuth consent screen |

> Example responses

> 200 Response

```json
{
  "success": true,
  "message": "Authentication successful",
  "authState": {
    "user": {
      "email": "user@example.com",
      "name": "John Doe",
      "imageUrl": "https://avatars.githubusercontent.com/u/1234567"
    },
    "token": "string",
    "accessToken": "string",
    "refreshToken": "string",
    "expiresAt": 0,
    "provider": "GITHUB"
  }
}
```

**Responses**

| Status | Meaning                                                 | Description               | Schema |
| ------ | ------------------------------------------------------- | ------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Authentication successful | Inline |

**Response Schema**

Status Code **200**

| Name            | Type    | Required | Restrictions | Description                              |
| --------------- | ------- | -------- | ------------ | ---------------------------------------- |
| » success       | boolean | false    | none         | none                                     |
| » message       | string  | false    | none         | none                                     |
| » authState     | object  | false    | none         | none                                     |
| »» user         | object  | false    | none         | none                                     |
| »»» email       | string  | false    | none         | User's email from GitHub                 |
| »»» name        | string  | false    | none         | User's display name from GitHub          |
| »»» imageUrl    | string  | false    | none         | User's profile image URL from GitHub     |
| »» token        | string  | false    | none         | JWT access token for API authentication  |
| »» accessToken  | string  | false    | none         | GitHub access token for GitHub API calls |
| »» refreshToken | string  | false    | none         | GitHub refresh token                     |
| »» expiresAt    | integer | false    | none         | Token expiration timestamp               |
| »» provider     | string  | false    | none         | Authentication provider                  |

**Enumerated Values**

| Property | Value  |
| -------- | ------ |
| provider | GITHUB |


# post\_\_auth\_github\_refresh

`POST /auth/github/refresh`

*Refresh GitHub Token*

Refresh GitHub OAuth access token using refresh token.

GitHub access tokens can expire or be revoked. Use this endpoint to get a new access token using the refresh token obtained during the initial OAuth flow.

**When to use:**

* GitHub access token has expired
* Need to continue using GitHub APIs
* Token was revoked and needs renewal

#### TypeScript Client Library

```typescript
private refreshGithubToken = async (refreshToken: string): Promise<RefreshTokenResponse> => {
  return this.makeRequest<RefreshTokenResponse>('auth/github/refresh', 'POST', {
    refresh_token: refreshToken,
  });
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/auth/github/refresh \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/auth/github/refresh HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "refresh_token": "gho_abc123..."
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/auth/github/refresh',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/auth/github/refresh',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/auth/github/refresh', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://backend.flashback.tech/auth/github/refresh', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/auth/github/refresh");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/auth/github/refresh", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Body parameter

```json
{
  "refresh_token": "gho_abc123..."
}
```

**Parameters**

| Name             | In   | Type   | Required | Description                                   |
| ---------------- | ---- | ------ | -------- | --------------------------------------------- |
| body             | body | object | true     | none                                          |
| » refresh\_token | body | string | true     | GitHub refresh token from previous OAuth flow |

> Example responses

> 200 Response

```json
{
  "success": true,
  "token": "string",
  "accessToken": "string",
  "refreshToken": "string",
  "expiresAt": 0
}
```

**Responses**

| Status | Meaning                                                 | Description              | Schema |
| ------ | ------------------------------------------------------- | ------------------------ | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Token refresh successful | Inline |

**Response Schema**

Status Code **200**

| Name           | Type    | Required | Restrictions | Description                                   |
| -------------- | ------- | -------- | ------------ | --------------------------------------------- |
| » success      | boolean | false    | none         | none                                          |
| » token        | string  | false    | none         | New GitHub access token                       |
| » accessToken  | string  | false    | none         | Same as token (for compatibility)             |
| » refreshToken | string  | false    | none         | Updated refresh token (if provided by GitHub) |
| » expiresAt    | integer | false    | none         | New token expiration timestamp                |


# post\_\_auth\_google\_refresh

`POST /auth/google/refresh`

*Refresh Google Token*

Refresh Google OAuth access token using refresh token.

Google access tokens expire after a short period. Use this endpoint to get a new access token using the refresh token obtained during the initial OAuth flow.

**When to use:**

* Access token has expired
* Need to continue using Google APIs
* Before calling `/auth/google` with an expired token

#### TypeScript Client Library

```typescript
private refreshGoogleToken = async (refreshToken: string): Promise<RefreshTokenResponse> => {
  return this.makeRequest<RefreshTokenResponse>('auth/google/refresh', 'POST', {
    refresh_token: refreshToken,
  });
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/auth/google/refresh \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/auth/google/refresh HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "refresh_token": "1//04dX..."
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/auth/google/refresh',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/auth/google/refresh',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/auth/google/refresh', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://backend.flashback.tech/auth/google/refresh', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/auth/google/refresh");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/auth/google/refresh", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Body parameter

```json
{
  "refresh_token": "1//04dX..."
}
```

**Parameters**

| Name             | In   | Type   | Required | Description                                   |
| ---------------- | ---- | ------ | -------- | --------------------------------------------- |
| body             | body | object | true     | none                                          |
| » refresh\_token | body | string | true     | Google refresh token from previous OAuth flow |

> Example responses

> 200 Response

```json
{
  "success": true,
  "token": "string",
  "refreshToken": "string",
  "expiresAt": 0
}
```

**Responses**

| Status | Meaning                                                 | Description              | Schema |
| ------ | ------------------------------------------------------- | ------------------------ | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Token refresh successful | Inline |

**Response Schema**

Status Code **200**

| Name           | Type    | Required | Restrictions | Description                                   |
| -------------- | ------- | -------- | ------------ | --------------------------------------------- |
| » success      | boolean | false    | none         | none                                          |
| » token        | string  | false    | none         | New Google access token                       |
| » refreshToken | string  | false    | none         | Updated refresh token (if provided by Google) |
| » expiresAt    | integer | false    | none         | New token expiration timestamp                |


# post\_\_auth\_google\_exchange

`POST /auth/google/exchange`

*Exchange Google Authorization Code*

Exchange Google authorization code for access token.

This endpoint completes the OAuth flow by exchanging an authorization code for an access token. Use this when you have an authorization code from the Google OAuth consent screen.

**OAuth Flow:**

1. Redirect user to Google OAuth consent screen
2. User authorizes your application
3. Google returns authorization code
4. Call this endpoint with the code
5. Receive access token for use with `/auth/google`

#### TypeScript Client Library

```typescript
private exchangeGoogleCode = async (code: string): Promise<OAuth2ResponseDTO> => {
  return this.makeRequest<OAuth2ResponseDTO>('auth/google/exchange', 'POST', { code });
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/auth/google/exchange \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/auth/google/exchange HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "code": "4/0AfJohXn..."
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/auth/google/exchange',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/auth/google/exchange',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/auth/google/exchange', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://backend.flashback.tech/auth/google/exchange', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/auth/google/exchange");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/auth/google/exchange", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Body parameter

```json
{
  "code": "4/0AfJohXn..."
}
```

**Parameters**

| Name   | In   | Type   | Required | Description                                         |
| ------ | ---- | ------ | -------- | --------------------------------------------------- |
| body   | body | object | true     | none                                                |
| » code | body | string | true     | Google authorization code from OAuth consent screen |

> Example responses

> 200 Response

```json
{
  "success": true,
  "token": "string",
  "refreshToken": "string",
  "expiresAt": 0
}
```

**Responses**

| Status | Meaning                                                 | Description               | Schema |
| ------ | ------------------------------------------------------- | ------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Token exchange successful | Inline |

**Response Schema**

Status Code **200**

| Name           | Type    | Required | Restrictions | Description                |
| -------------- | ------- | -------- | ------------ | -------------------------- |
| » success      | boolean | false    | none         | none                       |
| » token        | string  | false    | none         | Google access token        |
| » refreshToken | string  | false    | none         | Google refresh token       |
| » expiresAt    | integer | false    | none         | Token expiration timestamp |


# User Account

The table below provides a categorized overview of the Flashgate API endpoints for user account management, grouped by functional area. Each section lists the available HTTP functions along with a concise description of their purpose, helping developers quickly understand how to manage user accounts, roles, and profiles.

{% hint style="info" %}
To perform these operations, you must be authenticated by means of one of the following methods: [BearerAuth](/support-reference/platform-api-reference/authentication#http-bearer-authentication).
{% endhint %}

## User Account Management API Calls

<table><thead><tr><th width="247.4000244140625">Method</th><th>API Reference</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:green;"><code>GET</code></mark><code>/user/profile</code></td><td><a href="/pages/Wr4WjL6JmqK0YFroXvOU"><strong>get__user_profile</strong></a></td><td>Get the current authenticated user's profile information.</td></tr><tr><td><mark style="color:green;"><code>GET</code></mark><code>/user/{userId}</code></td><td><a href="/pages/F0Q5oAoLFr1NT2Mt5OUF"><strong>get__user_{userId}</strong></a></td><td>Get role information for a specific user within the same organization.</td></tr><tr><td><mark style="color:green;"><code>GET</code></mark><code>/user/quota</code></td><td><a href="/pages/HgPmJCeHeulSYnXSikAs"><strong>get__user_quota</strong></a></td><td>Get the current organization’s active subscription and quota usage.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/user/login</code></td><td><a href="/pages/FPU58yvF4BjOGsr6rdLa"><strong>post__user_login</strong></a></td><td>Log in an existing user using credentials.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/user/refresh</code></td><td><a href="/pages/APUdZSpDM2IGpZfkP86R"><strong>post__user_refresh</strong></a></td><td>Refresh JWT access token using a refresh token.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/user/register</code></td><td><a href="/pages/MXoPWsl229TaoHPgC2ap"><strong>post__user_register</strong></a></td><td>Register a new user with email and password.</td></tr><tr><td><mark style="color:blue;"><code>PUT</code></mark><code>/user/{userId}</code></td><td><a href="/pages/ybSqh6fNfSorWVUl1sTp"><strong>put__user_{userid}</strong></a></td><td>Fetch the organization’s active subscription and quota usage.</td></tr><tr><td><mark style="color:blue;"><code>PUT</code></mark><code>/user/{userId}/role</code></td><td><a href="/pages/nzkjHvmQuaYNB7USv0Pl"><strong>put__user_{userId}_role</strong></a></td><td>Update the organization role for a specific user.</td></tr></tbody></table>


# get\_\_user\_profile

`GET /user/profile`

*Get Current User Profile*

Retrieve the profile information for the currently authenticated user, including their organization role and permissions.

#### TypeScript Client Library

```typescript
public getUserProfile = async (): Promise<UserProfileResponse> => {
  return this.makeRequest<UserProfileResponse>('user/profile', 'GET', null);
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X GET https://backend.flashback.tech/user/profile \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
GET https://backend.flashback.tech/user/profile HTTP/1.1
Host: localhost:3000
Accept: application/json
Authorization: Bearer {access-token}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/user/profile',
{
  method: 'GET',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.get 'https://backend.flashback.tech/user/profile',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.get('https://backend.flashback.tech/user/profile', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

try {
    $response = $client->request('GET','https://backend.flashback.tech/user/profile', array(
        'headers' => $headers,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/user/profile");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{})
    req, err := http.NewRequest("GET", "https://backend.flashback.tech/user/profile", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Example responses

> 200 Response

```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "orgId": "123e4567-e89b-12d3-a456-426614174000",
    "orgRole": 2,
    "orgRoleDescription": "WORKSPACES",
    "orgRoles": [0, 1, 2],
    "validated": true,
    "mfaRequired": false
  }
}
```

> 404 Response

```json
{
  "success": false,
  "message": "User not found"
}
```

> 500 Response

```json
{
  "success": false,
  "message": "Internal server error",
  "error": "Database connection failed"
}
```

#### Responses <a href="#get__user_profile-responses" id="get__user_profile-responses"></a>

| Status | Meaning                                                                    | Description                         | Schema |
| ------ | -------------------------------------------------------------------------- | ----------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | User profile retrieved successfully | Inline |
| 404    | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)             | User not found                      | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error               | Inline |

#### Response Schema <a href="#get__user_profile-responseschema" id="get__user_profile-responseschema"></a>

Status Code **200**

| Name                  | Type       | Required | Restrictions | Description                                     |
| --------------------- | ---------- | -------- | ------------ | ----------------------------------------------- |
| » success             | boolean    | false    | none         | Indicates if the request was successful         |
| » data                | object     | false    | none         | User profile data                               |
| »» id                 | string     | false    | none         | Unique identifier for the user                  |
| »» name               | string     | false    | none         | User's first name                               |
| »» lastName           | string     | false    | none         | User's last name                                |
| »» email              | string     | false    | none         | User's email address                            |
| »» orgId              | string     | false    | none         | Organization identifier                         |
| »» orgRole            | integer    | false    | none         | User's organization role (0x00-0xff)            |
| »» orgRoleDescription | string     | false    | none         | Human-readable role description                 |
| »» orgRoles           | \[integer] | false    | none         | Array of available roles for the user           |
| »» validated          | boolean    | false    | none         | Whether the user's email is validated           |
| »» mfaRequired        | boolean    | false    | none         | Whether multi-factor authentication is required |

Status Code **404**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Error message describing the issue      |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Error message describing the issue      |
| » error   | string  | false    | none         | Detailed error information              |

**Enumerated Values**

| Parameter | Value | Description                                         |
| --------- | ----- | --------------------------------------------------- |
| » orgRole | 0x00  | USER - Default role with basic access               |
| » orgRole | 0x01  | BILLING - Can manage billing and subscriptions      |
| » orgRole | 0x02  | WORKSPACES - Can manage workspaces and team members |
| » orgRole | 0xfe  | ADMINISTRATORS - Administrative access              |
| » orgRole | 0xff  | OWNER - Full organization access                    |


# get\_\_user\_{userId}

`GET /user/{userId}`

*Get User by ID*

Retrieve role information for a specific user within the same organization. This endpoint allows organization members to view each other's roles and permissions.

#### TypeScript Client Library

```typescript
public getUserById = async (userId: string): Promise<UserRoleResponse> => {
  return this.makeRequest<UserRoleResponse>(`user/${userId}`, 'GET', null);
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X GET https://backend.flashback.tech/user/{userId} \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
GET https://backend.flashback.tech/user/{userId} HTTP/1.1
Host: localhost:3000
Accept: application/json
Authorization: Bearer {access-token}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/user/{userId}',
{
  method: 'GET',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.get 'https://backend.flashback.tech/user/{userId}',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.get('https://backend.flashback.tech/user/{userId}', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

try {
    $response = $client->request('GET','https://backend.flashback.tech/user/{userId}', array(
        'headers' => $headers,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/user/{userId}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{})
    req, err := http.NewRequest("GET", "https://backend.flashback.tech/user/{userId}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

#### Parameters <a href="#get__user_-userid-parameters" id="get__user_-userid-parameters"></a>

| Name   | In   | Type   | Required | Description                          |
| ------ | ---- | ------ | -------- | ------------------------------------ |
| userId | path | string | true     | Unique identifier of the target user |

> Example responses

> 200 Response

```json
{
  "success": true,
  "data": {
    "userId": "550e8400-e29b-41d4-a716-446655440000",
    "orgRole": 2,
    "orgRoleDescription": "WORKSPACES",
    "orgRoles": [0, 1, 2]
  }
}
```

> 403 Response

```json
{
  "success": false,
  "message": "User not associated with any organization"
}
```

> 404 Response

```json
{
  "success": false,
  "message": "User not found"
}
```

> 500 Response

```json
{
  "success": false,
  "message": "Internal server error",
  "error": "Database connection failed"
}
```

#### Responses <a href="#get__user_-userid-responses" id="get__user_-userid-responses"></a>

| Status | Meaning                                                                    | Description                      | Schema |
| ------ | -------------------------------------------------------------------------- | -------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | User role retrieved successfully | Inline |
| 403    | [Forbidden](https://tools.ietf.org/html/rfc7231#section-6.5.3)             | Access denied                    | Inline |
| 404    | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)             | User not found                   | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error            | Inline |

#### Response Schema <a href="#get__user_-userid-responseschema" id="get__user_-userid-responseschema"></a>

Status Code **200**

| Name                  | Type       | Required | Restrictions | Description                             |
| --------------------- | ---------- | -------- | ------------ | --------------------------------------- |
| » success             | boolean    | false    | none         | Indicates if the request was successful |
| » data                | object     | false    | none         | User role data                          |
| »» userId             | string     | false    | none         | Unique identifier for the target user   |
| »» orgRole            | integer    | false    | none         | User's organization role (0x00-0xff)    |
| »» orgRoleDescription | string     | false    | none         | Human-readable role description         |
| »» orgRoles           | \[integer] | false    | none         | Array of available roles for the user   |

Status Code **403**

| Name      | Type    | Required | Restrictions | Description                                     |
| --------- | ------- | -------- | ------------ | ----------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful         |
| » message | string  | false    | none         | Error message describing the access restriction |

Status Code **404**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Error message describing the issue      |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Error message describing the issue      |
| » error   | string  | false    | none         | Detailed error information              |

**Enumerated Values**

| Parameter | Value | Description                                         |
| --------- | ----- | --------------------------------------------------- |
| » orgRole | 0x00  | USER - Default role with basic access               |
| » orgRole | 0x01  | BILLING - Can manage billing and subscriptions      |
| » orgRole | 0x02  | WORKSPACES - Can manage workspaces and team members |
| » orgRole | 0xfe  | ADMINISTRATORS - Administrative access              |
| » orgRole | 0xff  | OWNER - Full organization access                    |


# get\_\_user\_quota

`GET /user/quota`

*Get Current User Quota and Usage*

Retrieve the current organization's active subscription information and quota usage for all capabilities associated with that subscription.

#### TypeScript Client Library

```typescript
public getUserQuota = async (): Promise<QuotaResponse> => {
  return this.makeRequest<QuotaResponse>('user/quota', 'GET', null);
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X GET https://backend.flashback.tech/user/quota \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
GET https://backend.flashback.tech/user/quota HTTP/1.1
Host: localhost:3000
Accept: application/json
Authorization: Bearer {access-token}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/user/quota',
{
  method: 'GET',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.get 'https://backend.flashback.tech/user/quota',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.get('https://backend.flashback.tech/user/quota', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

try {
    $response = $client->request('GET','https://backend.flashback.tech/user/quota', array(
        'headers' => $headers,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/user/quota");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{})
    req, err := http.NewRequest("GET", "https://backend.flashback.tech/user/quota", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Example responses

> 200 Response

```json
{
  "success": true,
  "subscription": {
    "id": "sub_123",
    "name": "Pro",
    "description": "Pro subscription"
  },
  "quotaUsage": [
    {
      "capability": {
        "id": "cap_001",
        "code": "STORAGE_TOTAL_BYTES",
        "description": "Total storage available in bytes",
        "type": "STORAGE",
        "periodType": "ALL_TIME"
      },
      "usage": {
        "current": 5368709120,
        "max": 10737418240,
        "percentage": 50
      }
    },
    {
      "capability": {
        "id": "cap_002",
        "code": "EGRESS_MONTHLY_BYTES",
        "description": "Monthly egress in bytes",
        "type": "TRAFFIC",
        "periodType": "MONTHLY"
      },
      "usage": {
        "current": 123456789,
        "max": 2147483648,
        "percentage": 6
      }
    }
  ]
}
```

> 401 Response

```json
{
  "success": false,
  "error_code": "NO_AUTH_USER"
}
```

> 404 Response

```json
{
  "success": false,
  "error_code": "NO_ACTIVE_SUBSCRIPTION"
}
```

> 500 Response

```json
{
  "success": false,
  "error_code": "INTERNAL_ERROR",
  "message": "Database connection failed"
}
```

#### Responses <a href="#get__user_quota-responses" id="get__user_quota-responses"></a>

| Status | Meaning                                                                    | Description                               | Schema |
| ------ | -------------------------------------------------------------------------- | ----------------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | Quota and usage retrieved successfully    | Inline |
| 401    | [Unauthorized](https://www.rfc-editor.org/rfc/rfc7235)                     | Authentication required or user not found | Inline |
| 404    | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)             | No active subscription                    | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error                     | Inline |

#### Response Schema <a href="#get__user_quota-responseschema" id="get__user_quota-responseschema"></a>

Status Code **200**

| Name            | Type      | Required | Restrictions | Description                                  |
| --------------- | --------- | -------- | ------------ | -------------------------------------------- |
| » success       | boolean   | false    | none         | Indicates if the request was successful      |
| » subscription  | object    | false    | none         | Active subscription info                     |
| »» id           | string    | false    | none         | Subscription identifier                      |
| »» name         | string    | false    | none         | Subscription name                            |
| »» description  | string    | false    | none         | Subscription description                     |
| » quotaUsage    | \[object] | false    | none         | Array of capability usage entries            |
| »» capability   | object    | false    | none         | Capability metadata                          |
| »»» id          | string    | false    | none         | Capability identifier                        |
| »»» code        | string    | false    | none         | Capability code                              |
| »»» description | string    | false    | none         | Capability description                       |
| »»» type        | string    | false    | none         | Capability type (e.g., 'STORAGE', 'TRAFFIC') |
| »»» periodType  | string    | false    | none         | Period type for quota accounting             |
| »» usage        | object    | false    | none         | Usage details                                |
| »»» current     | number    | false    | none         | Current usage value                          |
| »»» max         | number    | false    | none         | Maximum allowed usage                        |
| »»» percentage  | number    | false    | none         | Usage percentage (0-100)                     |

Status Code **401**

| Name          | Type    | Required | Restrictions | Description                             |
| ------------- | ------- | -------- | ------------ | --------------------------------------- |
| » success     | boolean | false    | none         | Indicates if the request was successful |
| » error\_code | string  | false    | none         | Error code, e.g., `NO_AUTH_USER`        |

Status Code **404**

| Name          | Type    | Required | Restrictions | Description                                |
| ------------- | ------- | -------- | ------------ | ------------------------------------------ |
| » success     | boolean | false    | none         | Indicates if the request was successful    |
| » error\_code | string  | false    | none         | Error code, e.g., `NO_ACTIVE_SUBSCRIPTION` |

Status Code **500**

| Name          | Type    | Required | Restrictions | Description                             |
| ------------- | ------- | -------- | ------------ | --------------------------------------- |
| » success     | boolean | false    | none         | Indicates if the request was successful |
| » error\_code | string  | false    | none         | Error code, e.g., `INTERNAL_ERROR`      |
| » message     | string  | false    | none         | Detailed error information              |

**Enumerated Values**

| Parameter    | Value     | Description              |
| ------------ | --------- | ------------------------ |
| » periodType | ALL\_TIME | No reset; lifetime quota |
| » periodType | DAILY     | Resets daily             |
| » periodType | WEEKLY    | Resets weekly            |
| » periodType | MONTHLY   | Resets monthly           |
| » periodType | YEARLY    | Resets yearly            |


# post\_\_user\_login

`POST /user/login`

*User Login*

Authenticate user with email and password.

This endpoint validates user credentials and returns JWT tokens for API access. The system checks:

* Email exists and is active
* Password matches stored hash
* Account is not deleted or banned

**Authentication Flow:**

1. Submit email and password
2. System validates credentials
3. Returns JWT access token and refresh token
4. Use access token in Authorization header for API calls
5. Use refresh token to get new access token when expired

**Token Expiration:**

* Access tokens expire after 1 hour
* Refresh tokens have longer expiration
* Use `/user/refresh` to renew access tokens

#### TypeScript Client Library

```typescript
public userLogin = async (data: LoginBody): Promise<LoginResponse> => {
  return this.makeRequest<LoginResponse>('user/login', 'POST', data);
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/user/login \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/user/login HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{\n  "email": "john.doe@company.com",\n  "password": "SecurePass123"\n}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/user/login',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/user/login',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/user/login', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://backend.flashback.tech/user/login', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/user/login");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/user/login", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Body parameter

```json
{
  "email": "john.doe@company.com",
  "password": "SecurePass123"
}
```

**Parameters**

| Name       | In   | Type          | Required | Description          |
| ---------- | ---- | ------------- | -------- | -------------------- |
| body       | body | object        | true     | none                 |
| » email    | body | string(email) | true     | User's email address |
| » password | body | string        | true     | User's password      |

> Example responses

> 200 Response

```json
{
  "success": true,
  "accessToken": "string",
  "refreshToken": "string",
  "tokenId": "string",
  "expiresAt": 0,
  "user": {
    "id": "string",
    "email": "string",
    "name": "string",
    "orgId": "string"
  }
}
```

**Responses**

| Status | Meaning                                                         | Description           | Schema |
| ------ | --------------------------------------------------------------- | --------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Login successful      | Inline |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | Authentication failed | Inline |

**Response Schema**

Status Code **200**

| Name           | Type    | Required | Restrictions | Description                             |
| -------------- | ------- | -------- | ------------ | --------------------------------------- |
| » success      | boolean | false    | none         | none                                    |
| » accessToken  | string  | false    | none         | JWT access token for API authentication |
| » refreshToken | string  | false    | none         | JWT refresh token for token renewal     |
| » tokenId      | string  | false    | none         | Internal token identifier               |
| » expiresAt    | integer | false    | none         | Access token expiration timestamp       |
| » user         | object  | false    | none         | none                                    |
| »» id          | string  | false    | none         | User's unique identifier                |
| »» email       | string  | false    | none         | User's email address                    |
| »» name        | string  | false    | none         | User's display name                     |
| »» orgId       | string  | false    | none         | Organization identifier                 |

Status Code **401**

| Name          | Type    | Required | Restrictions | Description                   |
| ------------- | ------- | -------- | ------------ | ----------------------------- |
| » success     | boolean | false    | none         | none                          |
| » error\_code | string  | false    | none         | Specific authentication error |

**Enumerated Values**

| Property    | Value             |
| ----------- | ----------------- |
| error\_code | USER\_NOT\_FOUND  |
| error\_code | INVALID\_PASSWORD |
| error\_code | USER\_INACTIVE    |
| error\_code | NO\_PASSWORD\_SET |

To perform this operation, you must be authenticated by means of one of the following methods: BearerAuth


# post\_\_user\_refresh

`POST /user/refresh`

*Refresh User Token*

Refresh JWT access token

#### TypeScript Client Library

```typescript
public userRefresh = async (refreshToken: string): Promise<RefreshTokenResponse | RefreshTokenErrorResponse> => {
  return this.makeRequest<RefreshTokenResponse | RefreshTokenErrorResponse>(
    'user/refresh',
    'POST',
    { refresh_token: refreshToken }
  );
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/user/refresh \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'

```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/user/refresh HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{\n  "refreshToken": "string"\n}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/user/refresh',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/user/refresh',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/user/refresh', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://backend.flashback.tech/user/refresh', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/user/refresh");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/user/refresh", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Body parameter

```json
{
  "refreshToken": "string"
}
```

**Parameters**

| Name           | In   | Type   | Required | Description |
| -------------- | ---- | ------ | -------- | ----------- |
| body           | body | object | true     | none        |
| » refreshToken | body | string | true     | none        |

> Example responses

> 200 Response

```json
{
  "success": true,
  "accessToken": "string",
  "refreshToken": "string",
  "expiresAt": 0
}
```

**Responses**

| Status | Meaning                                                 | Description              | Schema |
| ------ | ------------------------------------------------------- | ------------------------ | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Token refresh successful | Inline |

**Response Schema**

Status Code **200**

| Name           | Type    | Required | Restrictions | Description |
| -------------- | ------- | -------- | ------------ | ----------- |
| » success      | boolean | false    | none         | none        |
| » accessToken  | string  | false    | none         | none        |
| » refreshToken | string  | false    | none         | none        |
| » expiresAt    | integer | false    | none         | none        |

To perform this operation, you must be authenticated by means of one of the following methods: BearerAuth


# post\_\_user\_register

`POST /user/register`

*Register User*

Register a new user with internal email/password authentication.

This endpoint creates a new user account and organization. The system automatically:

* Validates email format and uniqueness
* Checks password complexity requirements
* Creates an organization based on company domain
* Assigns a free trial subscription
* Sends email verification

**Password Requirements:**

* Minimum 8 characters
* Must contain uppercase letter
* Must contain lowercase letter
* Must contain number

**Email Verification:**

* Verification email sent immediately after registration
* Verification tokens expire after 24 hours
* Write operations blocked until email verification

**Account Types:**

* **Personal**: Use `isBusiness: false` for personal accounts
* **Business**: Use `isBusiness: true` for business accounts with company details

#### TypeScript Client Library

```typescript
public userRegister = async (data: RegisterBody): Promise<RegisterResponse> => {
  return this.makeRequest<RegisterResponse>('user/register', 'POST', data);
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/user/register \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/user/register HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "email": "john.doe@company.com",
  "password": "SecurePass123",
  "firstName": "John",
  "lastName": "Doe",
  "companyName": "Acme Corporation",
  "companyWebsite": "https://acme.com",
  "isBusiness": true
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/user/register',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/user/register',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/user/register', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://backend.flashback.tech/user/register', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/user/register");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/user/register", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Body parameter

```json
{
  "email": "john.doe@company.com",
  "password": "SecurePass123",
  "firstName": "John",
  "lastName": "Doe",
  "companyName": "Acme Corporation",
  "companyWebsite": "https://acme.com",
  "isBusiness": true
}
```

**Parameters**

| Name             | In   | Type          | Required | Description                                          |
| ---------------- | ---- | ------------- | -------- | ---------------------------------------------------- |
| body             | body | object        | true     | none                                                 |
| » email          | body | string(email) | true     | User's email address (must be unique)                |
| » password       | body | string        | true     | Password meeting complexity requirements             |
| » firstName      | body | string        | true     | User's first name                                    |
| » lastName       | body | string        | true     | User's last name                                     |
| » companyName    | body | string        | true     | Company or organization name                         |
| » companyWebsite | body | string        | false    | Company website URL (optional for personal accounts) |
| » isBusiness     | body | boolean       | true     | Whether this is a business account                   |

> Example responses

> 201 Response

```json
{
  "success": true,
  "accessToken": "string",
  "refreshToken": "string",
  "tokenId": "string",
  "user": {
    "id": "string",
    "email": "string",
    "name": "string",
    "orgId": "string",
    "image_url": "string"
  }
}
```

**Responses**

| Status | Meaning                                                          | Description                  | Schema |
| ------ | ---------------------------------------------------------------- | ---------------------------- | ------ |
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)     | User registered successfully | Inline |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1) | Registration failed          | Inline |

**Response Schema**

Status Code **201**

| Name           | Type    | Required | Restrictions | Description                             |
| -------------- | ------- | -------- | ------------ | --------------------------------------- |
| » success      | boolean | false    | none         | none                                    |
| » accessToken  | string  | false    | none         | JWT access token for API authentication |
| » refreshToken | string  | false    | none         | JWT refresh token for token renewal     |
| » tokenId      | string  | false    | none         | Internal token identifier               |
| » user         | object  | false    | none         | none                                    |
| »» id          | string  | false    | none         | User's unique identifier                |
| »» email       | string  | false    | none         | User's email address                    |
| »» name        | string  | false    | none         | User's display name                     |
| »» orgId       | string  | false    | none         | Organization identifier                 |
| »» image\_url  | string  | false    | none         | User's profile image URL                |

Status Code **400**

| Name          | Type    | Required | Restrictions | Description                  |
| ------------- | ------- | -------- | ------------ | ---------------------------- |
| » success     | boolean | false    | none         | none                         |
| » error\_code | string  | false    | none         | Specific error code          |
| » message     | string  | false    | none         | Human-readable error message |

**Enumerated Values**

| Property    | Value                   |
| ----------- | ----------------------- |
| error\_code | EMAIL\_EXISTS\_ACTIVE   |
| error\_code | EMAIL\_EXISTS\_INACTIVE |
| error\_code | WEAK\_PASSWORD          |
| error\_code | INVALID\_INPUT          |
| error\_code | ORG\_BANNED             |


# put\_\_user\_{userId}

`PUT /user/{userId}`

*Update User Basic Data*

Update basic user information for a specific user within your organization. This endpoint allows authorized users to modify user profile data including name, last name, and password (for non-provider users). The endpoint includes comprehensive validation to ensure proper permissions, organization membership, and data security.

#### User Data Management

Flashgate provides granular control over user profile management with role-based permissions and security validations. This endpoint supports updating basic user information while maintaining strict security boundaries and data integrity.

**Supported Update Fields:**

| Field    | Type   | Required | Description       | Restrictions                                                 |
| -------- | ------ | -------- | ----------------- | ------------------------------------------------------------ |
| name     | string | false    | User's first name | Must be a valid string if provided                           |
| lastName | string | false    | User's last name  | Must be a valid string if provided                           |
| password | string | false    | User's password   | Only for non-provider users, must meet security requirements |

**Key Features:**

1. **Role-Based Access Control**: Users can only modify data based on their organization role and relationship to the target user
2. **Provider User Protection**: Users with external authentication providers (OAuth, etc.) cannot have their passwords modified
3. **Organization Isolation**: Users can only modify data within their own organization
4. **Password Security**: Password updates include validation and secure hashing
5. **Audit Trail**: All updates are logged as system events for compliance and monitoring

**Permission Requirements:**

* **Self-Modification**: Any user can update their own basic data (name, lastName)
* **Password Updates**: Users can only update their own password
* **Administrative Access**: Users with WORKSPACES, ADMINISTRATORS, or OWNER roles can modify other users' basic data
* **Organization Membership**: Both current user and target user must be in the same organization

#### TypeScript Client Library

```typescript
public updateUser = async (userId: string, data: UserUpdateRequest): Promise<UserUpdateResponse> => {
  return this.makeRequest<UserUpdateResponse>(`user/${userId}`, 'PUT', data);
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# Update user's name and last name
curl -X PUT https://backend.flashback.tech/user/{userId} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -d '{
    "name": "John",
    "lastName": "Doe"
  }'

# Update user's password (non-provider users only)
curl -X PUT https://backend.flashback.tech/user/{userId} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -d '{
    "password": "NewSecurePassword123!"
  }'
```

{% endtab %}

{% tab title="HTTP" %}

```http
PUT https://backend.flashback.tech/user/{userId} HTTP/1.1
Host: backend.flashback.tech
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access-token}

{
  "name": "John",
  "lastName": "Doe"
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "name": "John",
  "lastName": "Doe"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/user/{userId}',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.put 'https://backend.flashback.tech/user/{userId}',
  {
    'name' => 'John',
    'lastName' => 'Doe'
  }.to_json, headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

data = {
  'name': 'John',
  'lastName': 'Doe'
}

r = requests.put('https://backend.flashback.tech/user/{userId}',
                 headers=headers,
                 json=data)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

$request_body = array(
    'name' => 'John',
    'lastName' => 'Doe'
);

try {
    $response = $client->request('PUT','https://backend.flashback.tech/user/{userId}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    print_r($e->getMessage());
 }
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/user/{userId}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
con.setDoOutput(true);

String jsonInputString = "{\"name\": \"John\", \"lastName\": \"Doe\"}";
try(OutputStream os = con.getOutputStream()) {
    byte[] input = jsonInputString.getBytes("utf-8");
    os.write(input, 0, input.length);
}

int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
       "encoding/json"
)

func main() {
    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := map[string]string{
        "name": "John",
        "lastName": "Doe",
    }
    jsonData, _ := json.Marshal(data)

    req, err := http.NewRequest("PUT", "https://backend.flashback.tech/user/{userId}", bytes.NewBuffer(jsonData))
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

#### Parameters <a href="#put__user_-userid-parameters" id="put__user_-userid-parameters"></a>

| Name   | In   | Type   | Required | Description                          |
| ------ | ---- | ------ | -------- | ------------------------------------ |
| userId | path | string | true     | Unique identifier of the target user |

#### Request Body <a href="#put__user_-userid-request-body" id="put__user_-userid-request-body"></a>

| Name     | Type   | Required | Description                               |
| -------- | ------ | -------- | ----------------------------------------- |
| name     | string | false    | User's first name                         |
| lastName | string | false    | User's last name                          |
| password | string | false    | User's password (non-provider users only) |

> Body parameter

```json
{
  "name": "John",
  "lastName": "Doe"
}
```

> Example responses

> 200 Response

```json
{
  "success": true,
  "message": "User data updated successfully"
}
```

> 400 Response (Provider User Password Update)

```json
{
  "success": false,
  "message": "Password cannot be changed for users with external authentication providers"
}
```

> 400 Response (Invalid Password)

```json
{
  "success": false,
  "message": "Password does not meet security requirements"
}
```

> 403 Response (Organization Mismatch)

```json
{
  "success": false,
  "message": "Access denied: users must be in the same organization"
}
```

> 403 Response (No Organization)

```json
{
  "success": false,
  "message": "User not associated with any organization"
}
```

> 403 Response (Insufficient Permissions)

```json
{
  "success": false,
  "message": "Access denied: insufficient permissions to modify user data"
}
```

> 404 Response

```json
{
  "success": false,
  "message": "User not found"
}
```

> 500 Response

```json
{
  "success": false,
  "message": "Internal server error",
  "error": "Database connection failed"
}
```

#### Responses <a href="#put__user_-userid-responses" id="put__user_-userid-responses"></a>

| Status | Meaning                                                                    | Description                                                                                                    | Schema |
| ------ | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | User data updated successfully                                                                                 | Inline |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)           | Invalid password or provider user password update                                                              | Inline |
| 403    | [Forbidden](https://tools.ietf.org/html/rfc7231#section-6.5.3)             | Access denied due to insufficient permissions, organization mismatch, or user not associated with organization | Inline |
| 404    | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)             | User not found                                                                                                 | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error                                                                                          | Inline |

#### Response Schema <a href="#put__user_-userid-responseschema" id="put__user_-userid-responseschema"></a>

Status Code **200**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Success message describing the update   |

Status Code **400**

| Name      | Type    | Required | Restrictions | Description                                   |
| --------- | ------- | -------- | ------------ | --------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful       |
| » message | string  | false    | none         | Error message describing the validation issue |

Status Code **403**

| Name      | Type    | Required | Restrictions | Description                                     |
| --------- | ------- | -------- | ------------ | ----------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful         |
| » message | string  | false    | none         | Error message describing the access restriction |

Status Code **404**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Error message describing the issue      |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Error message describing the issue      |
| » error   | string  | false    | none         | Detailed error information              |

#### Security & Validation

This endpoint includes comprehensive validation and security checks:

**Organization Membership Validation**

* Both the current user and target user must be associated with the same organization
* Users not associated with any organization cannot perform user updates

**Permission Validation**

* Users can always update their own basic data (name, lastName)
* Password updates are restricted to the user's own account
* Administrative users (WORKSPACES, ADMINISTRATORS, OWNER) can modify other users' basic data
* Role-based access control ensures proper permission boundaries

**Provider User Protection**

* Users with external authentication providers (OAuth, SAML, etc.) cannot have their passwords modified
* This prevents conflicts with external identity management systems

**Password Security Validation**

* Password updates include comprehensive security validation
* Passwords are securely hashed using industry-standard algorithms
* Password requirements are enforced to maintain security standards

**Data Integrity**

* All updates are validated for data type and format
* System events are generated for audit and compliance purposes
* Changes are logged with before/after data for tracking

**Authentication Required**

* Valid access token must be provided in the Authorization header
* User must be authenticated and associated with an organization


# put\_\_user\_{userId}\_role

`PUT /user/{userId}/role`

*Update User Role*

Update the organization role for a specific user. This endpoint allows authorized users to modify role assignments within their organization. The endpoint includes comprehensive validation to ensure proper permissions, organization membership, and role combination validity.

#### Organization Role System

Flashgate uses a **flag-based role system** where each role is represented by a hexadecimal value. This system provides granular control over user permissions and allows for future role expansion.

**Role Hierarchy (from lowest to highest privilege):**

| Role Value | Hex Code | Role Name          | Description               | Permissions                                                                           |
| ---------- | -------- | ------------------ | ------------------------- | ------------------------------------------------------------------------------------- |
| 0          | 0x00     | **USER**           | Default role - basic user | Basic access to assigned resources, view-only access to organization settings         |
| 1          | 0x01     | **BILLING**        | Billing management        | Can manage billing, subscriptions, payment methods, and view usage reports            |
| 2          | 0x02     | **WORKSPACES**     | Workspace management      | Can create, modify, and delete workspaces, manage team members, and assign user roles |
| 254        | 0xfe     | **ADMINISTRATORS** | Administrative access     | Full administrative control, can manage all aspects except ownership transfer         |
| 255        | 0xff     | **OWNER**          | Full organization access  | Complete control over the organization, including ownership transfer and deletion     |

**Key Features of the Flag-Based System:**

1. **Scalable Design**: The system reserves values between 0x03 and 0xfd for future role types, allowing for up to 251 additional custom roles.
2. **Permission Inheritance**: Higher-level roles automatically inherit permissions from lower-level roles. For example, a WORKSPACES user can perform all USER and BILLING operations.
3. **Role Modification Rules**: Users can only modify roles that are at or below their own permission level. An OWNER can modify any role, while a WORKSPACES user can only modify USER and BILLING roles.
4. **Organization Protection**: The system prevents the last OWNER from removing their role, ensuring organizations always have at least one owner.
5. **Cross-Organization Isolation**: Users can only modify roles within their own organization, maintaining strict security boundaries.

**Common Use Cases:**

* **Startup Teams**: Begin with USER roles for most team members, promote key members to WORKSPACES for project management
* **Enterprise Organizations**: Use ADMINISTRATORS for IT teams, BILLING for finance teams, and WORKSPACES for project managers
* **Multi-Department Companies**: Assign BILLING roles to finance teams, WORKSPACES to engineering teams, and maintain ADMINISTRATORS for system administration

#### TypeScript Client Library

```typescript
public updateUserRole = async (userId: string, orgRole: number): Promise<UpdateUserRoleResponse> => {
  return this.makeRequest<UpdateUserRoleResponse>(`user/${userId}/role`, 'PUT', { orgRole });
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X PUT https://backend.flashback.tech/user/{userId}/role \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -d '{
    "orgRole": 2
  }'
```

{% endtab %}

{% tab title="HTTP" %}

```http
PUT https://backend.flashback.tech/user/{userId}/role HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access-token}

{
  "orgRole": 2
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "orgRole": 2
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/user/{userId}/role',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.put 'https://backend.flashback.tech/user/{userId}/role',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.put('https://backend.flashback.tech/user/{userId}/role', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array(
    'orgRole' => 2
);

try {
    $response = $client->request('PUT','https://backend.flashback.tech/user/{userId}/role', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/user/{userId}/role");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
con.setDoOutput(true);

String jsonInputString = "{\"orgRole\": 2}";
try(OutputStream os = con.getOutputStream()) {
    byte[] input = jsonInputString.getBytes("utf-8");
    os.write(input, 0, input.length);
}

int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{`{"orgRole": 2}`})
    req, err := http.NewRequest("PUT", "https://backend.flashback.tech/user/{userId}/role", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

#### Parameters <a href="#put__user_-userid-_role-parameters" id="put__user_-userid-_role-parameters"></a>

| Name   | In   | Type   | Required | Description                          |
| ------ | ---- | ------ | -------- | ------------------------------------ |
| userId | path | string | true     | Unique identifier of the target user |

#### Request Body <a href="#put__user_-userid-_role-request-body" id="put__user_-userid-_role-request-body"></a>

| Name    | Type    | Required | Description                             |
| ------- | ------- | -------- | --------------------------------------- |
| orgRole | integer | true     | New organization role value (0x00-0xff) |

> Body parameter

```json
{
  "orgRole": 2
}
```

> Example responses

> 200 Response

```json
{
  "success": true,
  "data": {
    "userId": "550e8400-e29b-41d4-a716-446655440000",
    "previousRole": 0,
    "newRole": 2,
    "message": "User role updated to WORKSPACES"
  }
}
```

> 400 Response

```json
{
  "success": false,
  "message": "Invalid role combination"
}
```

> 400 Response (Owner Role Protection)

```json
{
  "success": false,
  "message": "Cannot remove OWNER role: must have at least one other user with OWNER role in the organization"
}
```

> 403 Response (Organization Mismatch)

```json
{
  "success": false,
  "message": "Access denied: users must be in the same organization"
}
```

> 403 Response (No Organization)

```json
{
  "success": false,
  "message": "User not associated with any organization"
}
```

> 403 Response (Insufficient Permissions)

```json
{
  "success": false,
  "message": "Access denied: insufficient permissions to modify user role"
}
```

> 404 Response

```json
{
  "success": false,
  "message": "User not found"
}
```

> 500 Response

```json
{
  "success": false,
  "message": "Internal server error",
  "error": "Database connection failed"
}
```

#### Responses <a href="#put__user_-userid-_role-responses" id="put__user_-userid-_role-responses"></a>

| Status | Meaning                                                                    | Description                                                                                                    | Schema |
| ------ | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | User role updated successfully                                                                                 | Inline |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)           | Invalid role combination or owner role removal restriction                                                     | Inline |
| 403    | [Forbidden](https://tools.ietf.org/html/rfc7231#section-6.5.3)             | Access denied due to insufficient permissions, organization mismatch, or user not associated with organization | Inline |
| 404    | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)             | User not found                                                                                                 | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error                                                                                          | Inline |

#### Response Schema <a href="#put__user_-userid-_role-responseschema" id="put__user_-userid-_role-responseschema"></a>

Status Code **200**

| Name            | Type    | Required | Restrictions | Description                                |
| --------------- | ------- | -------- | ------------ | ------------------------------------------ |
| » success       | boolean | false    | none         | Indicates if the request was successful    |
| » data          | object  | false    | none         | Role update confirmation data              |
| »» userId       | string  | false    | none         | Unique identifier for the target user      |
| »» previousRole | integer | false    | none         | User's previous organization role          |
| »» newRole      | integer | false    | none         | User's new organization role               |
| »» message      | string  | false    | none         | Confirmation message describing the change |

Status Code **400**

| Name      | Type    | Required | Restrictions | Description                                   |
| --------- | ------- | -------- | ------------ | --------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful       |
| » message | string  | false    | none         | Error message describing the validation issue |

Status Code **403**

| Name      | Type    | Required | Restrictions | Description                                     |
| --------- | ------- | -------- | ------------ | ----------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful         |
| » message | string  | false    | none         | Error message describing the access restriction |

Status Code **404**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Error message describing the issue      |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Error message describing the issue      |
| » error   | string  | false    | none         | Detailed error information              |

**Enumerated Values**

| Parameter | Value | Description                                         |
| --------- | ----- | --------------------------------------------------- |
| » orgRole | 0x00  | USER - Default role with basic access               |
| » orgRole | 0x01  | BILLING - Can manage billing and subscriptions      |
| » orgRole | 0x02  | WORKSPACES - Can manage workspaces and team members |
| » orgRole | 0xfe  | ADMINISTRATORS - Administrative access              |
| » orgRole | 0xff  | OWNER - Full organization access                    |

#### Security & Validation

This endpoint includes comprehensive validation and security checks:

**Organization Membership Validation**

* Both the current user and target user must be associated with the same organization
* Users not associated with any organization cannot perform role updates

**Permission Validation**

* Current user must have sufficient permissions to modify the target user's role
* Role modification follows hierarchical permission rules

**Role Combination Validation**

* The requested role combination must be valid according to business rules
* Invalid role combinations are rejected with a 400 status

**Owner Role Protection**

* Users cannot remove their own OWNER role unless there's at least one other user with OWNER role in the organization
* This prevents organizations from being left without an owner

**Authentication Required**

* Valid access token must be provided in the Authorization header
* User must be authenticated and associated with an organization


# MFA (multi-factor authentication)

The table below provides a comprehensive overview of the Flashgate API multi-factor authentication endpoints, grouped by functional area. Each section lists the available HTTP functions along with a concise description of their purpose, helping developers understand how to implement secure multi-factor authentication.

{% hint style="info" %}
Multi-factor authentication enhances security by requiring users to provide additional verification beyond their password. The Flashgate platform supports multiple MFA methods including Google Authenticator, Magic Links, and WebAuthn Passkeys.
{% endhint %}

## MFA Status & Methods API Calls

<table><thead><tr><th width="247.4000244140625">Method</th><th>API Reference</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:green;"><code>GET</code></mark><code>/mfa/status</code></td><td><a href="/pages/7huB9qhrOHa5rTkzhOv5"><strong>get__mfa_status</strong></a></td><td>Get the current MFA status for the authenticated user.</td></tr><tr><td><mark style="color:green;"><code>GET</code></mark><code>/mfa/methods</code></td><td><a href="/pages/MSGpLKFmMcRKSy4lv2mi"><strong>get__mfa_methods</strong></a></td><td>Get available MFA methods and their configuration status.</td></tr></tbody></table>

## MFA Setup & Configuration API Calls

<table><thead><tr><th width="247.4000244140625">Method</th><th>API Reference</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/setup</code></td><td><a href="/pages/LtgxzybCNAPJSIUTpitT"><strong>post_mfa_setup</strong></a></td><td>Initialize setup for an MFA method.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/verify-setup</code></td><td><a href="/pages/w9LRGcv3pVy7NaZ3iLMi"><strong>post__mfa_verify-setup</strong></a></td><td>Verify and complete MFA setup process.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/enable</code></td><td><a href="/pages/ktJp8dKpC9YC2LMO6v1T"><strong>post__mfa_enable</strong></a></td><td>Enable a configured MFA method.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/disable</code></td><td><a href="/pages/pOWQFOHsws9cRYwDFkz3"><strong>post_mfa_disable</strong></a></td><td>Disable an enabled MFA method.</td></tr></tbody></table>

## MFA Management API Calls

<table><thead><tr><th width="247.4000244140625">Method</th><th>API Reference</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/primary</code></td><td><a href="/pages/r8cNuwqdot7MUJnkR0zM"><strong>post__mfa_primary</strong></a></td><td>Set the primary MFA method for the user.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/reset</code></td><td><a href="/pages/JwFFImrXYF1Av3EgpN0u"><strong>post__mfa_reset</strong></a></td><td>Reset user's MFA configuration (self-service).</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/organization/enforce</code></td><td><a href="/pages/oV1F0iqXizMJiQH6At4y"><strong>post__mfa_organization_enforce</strong></a></td><td>Enforce MFA for organization members (admin only).</td></tr></tbody></table>

## Magic Link MFA API Calls

<table><thead><tr><th width="247.4000244140625">Method</th><th>API Reference</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/magic-link/send</code></td><td><a href="/pages/VLTiY40YLrMBqMJ4Mftc"><strong>post__mfa_magic-link_send</strong></a></td><td>Send magic link for MFA verification.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/magic-link/activate</code></td><td><a href="/pages/L1ZeJIpFgm2TL195mCs4"><strong>post__mfa_magic-link_activate</strong></a></td><td>Activate magic link MFA during setup.</td></tr></tbody></table>

## Passkey MFA API Calls

<table><thead><tr><th width="247.4000244140625">Method</th><th>API Reference</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/passkey/auth-options</code></td><td><a href="/pages/CVZQcitcnMmfC6jueupJ"><strong>post__passkey_auth-options</strong></a></td><td>Generate authentication options for passkeys.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/passkey/complete-registration</code></td><td><a href="/pages/3MFQTEJvaa9GcgUhN85Q"><strong>post__mfa_passkey_complete-registration</strong></a></td><td>Complete passkey registration process.</td></tr><tr><td><mark style="color:orange;"><code>POST</code></mark><code>/mfa/passkey/complete-registration-1</code></td><td><a href="/pages/aJ0XcGZjb0uazhfdCcmf"><strong>post__mfa_passkey_complete-registration-1</strong></a></td><td>Alternative passkey registration endpoint.</td></tr></tbody></table>

## MFA Authentication Flow

### 1. **Setup Phase**

* User initiates MFA setup with `/mfa/setup`
* System generates configuration data (QR codes, challenges, etc.)
* User completes verification with `/mfa/verify-setup`
* MFA method is enabled with `/mfa/enable`

### 2. **Authentication Phase**

* User provides primary credentials (username/password)
* System prompts for MFA verification
* User completes MFA challenge
* Full access is granted upon successful verification

### 3. **Management Phase**

* Users can manage their MFA methods
* Set primary MFA method
* Enable/disable specific methods
* Reset MFA configuration when needed

## Supported MFA Methods

* **Google Authenticator**: Time-based one-time passwords (TOTP)
* **Magic Links**: Secure email-based authentication
* **Passkeys**: WebAuthn-based biometric or hardware key authentication

{% hint style="warning" %}
**Security Note**: MFA significantly enhances account security. Always use HTTPS in production and ensure proper session management. Users should have backup MFA methods configured.
{% endhint %}


# get\_\_mfa\_status

`GET /mfa/status`

*Get MFA Status*

Retrieve the current multi-factor authentication status for the authenticated user, including enabled methods and enforcement settings.

#### TypeScript Client Library

```typescript
// Note: This endpoint doesn't have a direct client method in the provided TypeScript client
// You would need to use the generic makeRequest method:
// this.makeRequest<any>('mfa/status', 'GET', null);
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X GET https://backend.flashback.tech/mfa/status \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
GET https://backend.flashback.tech/mfa/status HTTP/1.1
Host: localhost:3000
Accept: application/json
Authorization: Bearer {access-token}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/mfa/status',
{
  method: 'GET',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.get 'https://backend.flashback.tech/mfa/status',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.get('https://backend.flashback.tech/mfa/status', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

try {
    $response = $client->request('GET','https://backend.flashback.tech/mfa/status', array(
        'headers' => $headers,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/mfa/status");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{})
    req, err := http.NewRequest("GET", "https://backend.flashback.tech/mfa/status", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Example responses

> 200 Response

```json
{
  "success": true,
  "data": {
    "isEnabled": true,
    "isRequired": false,
    "isEnforced": false,
    "enabledMethods": ["GOOGLE_AUTH", "PASSKEY"],
    "primaryMethod": "GOOGLE_AUTH"
  }
}
```

> 500 Response

```json
{
  "success": false,
  "error": "Failed to get MFA status"
}
```

#### Responses <a href="#get__mfa_status-responses" id="get__mfa_status-responses"></a>

| Status | Meaning                                                                    | Description                       | Schema |
| ------ | -------------------------------------------------------------------------- | --------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | MFA status retrieved successfully | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error             | Inline |

#### Response Schema <a href="#get__mfa_status-responseschema" id="get__mfa_status-responseschema"></a>

Status Code **200**

| Name              | Type      | Required | Restrictions | Description                             |
| ----------------- | --------- | -------- | ------------ | --------------------------------------- |
| » success         | boolean   | false    | none         | Indicates if the request was successful |
| » data            | object    | false    | none         | MFA status information                  |
| »» isEnabled      | boolean   | false    | none         | Whether MFA is enabled for the user     |
| »» isRequired     | boolean   | false    | none         | Whether MFA is required for the user    |
| »» isEnforced     | boolean   | false    | none         | Whether MFA is enforced by organization |
| »» enabledMethods | \[string] | false    | none         | Array of enabled MFA method types       |
| »» primaryMethod  | string    | false    | none         | The user's primary MFA method           |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |

**Enumerated Values**

| Parameter        | Value        | Description                     |
| ---------------- | ------------ | ------------------------------- |
| » enabledMethods | GOOGLE\_AUTH | Google Authenticator TOTP       |
| » enabledMethods | MAGIC\_LINK  | Magic link email verification   |
| » enabledMethods | PASSKEY      | WebAuthn passkey authentication |
| » primaryMethod  | GOOGLE\_AUTH | Google Authenticator TOTP       |
| » primaryMethod  | MAGIC\_LINK  | Magic link email verification   |
| » primaryMethod  | PASSKEY      | WebAuthn passkey authentication |


# get\_\_mfa\_methods

`GET /mfa/methods`

*Get Available MFA Methods*

Retrieve all available multi-factor authentication methods for the authenticated user, including their configuration status and availability.

#### TypeScript Client Library

```typescript
// Note: This endpoint doesn't have a direct client method in the provided TypeScript client
// You would need to use the generic makeRequest method:
// this.makeRequest<any>('mfa/methods', 'GET', null);
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X GET https://backend.flashback.tech/mfa/methods \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
GET https://backend.flashback.tech/mfa/methods HTTP/1.1
Host: localhost:3000
Accept: application/json
Authorization: Bearer {access-token}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/mfa/methods',
{
  method: 'GET',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.get 'https://backend.flashback.tech/mfa/methods',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.get('https://backend.flashback.tech/mfa/methods', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

try {
    $response = $client->request('GET','https://backend.flashback.tech/mfa/methods', array(
        'headers' => $headers,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/mfa/methods");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{})
    req, err := http.NewRequest("GET", "https://backend.flashback.tech/mfa/methods", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Example responses

> 200 Response

```json
{
  "success": true,
  "data": [
    {
      "type": "GOOGLE_AUTH",
      "name": "Google Authenticator",
      "description": "Time-based one-time password using Google Authenticator app",
      "isAvailable": true,
      "isConfigured": true,
      "isEnabled": true
    },
    {
      "type": "MAGIC_LINK",
      "name": "Magic Link",
      "description": "Email-based authentication using secure links",
      "isAvailable": true,
      "isConfigured": false,
      "isEnabled": false
    },
    {
      "type": "PASSKEY",
      "name": "Passkey",
      "description": "WebAuthn-based biometric or hardware key authentication",
      "isAvailable": true,
      "isConfigured": true,
      "isEnabled": true
    }
  ]
}
```

> 500 Response

```json
{
  "success": false,
  "error": "Failed to get MFA methods"
}
```

#### Responses <a href="#get__mfa_methods-responses" id="get__mfa_methods-responses"></a>

| Status | Meaning                                                                    | Description                        | Schema |
| ------ | -------------------------------------------------------------------------- | ---------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | MFA methods retrieved successfully | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error              | Inline |

#### Response Schema <a href="#get__mfa_methods-responseschema" id="get__mfa_methods-responseschema"></a>

Status Code **200**

| Name            | Type      | Required | Restrictions | Description                                   |
| --------------- | --------- | -------- | ------------ | --------------------------------------------- |
| » success       | boolean   | false    | none         | Indicates if the request was successful       |
| » data          | \[object] | false    | none         | Array of available MFA methods                |
| »» type         | string    | false    | none         | MFA method type identifier                    |
| »» name         | string    | false    | none         | Human-readable method name                    |
| »» description  | string    | false    | none         | Detailed description of the method            |
| »» isAvailable  | boolean   | false    | none         | Whether the method is available for setup     |
| »» isConfigured | boolean   | false    | none         | Whether the method is configured for the user |
| »» isEnabled    | boolean   | false    | none         | Whether the method is currently enabled       |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |

**Enumerated Values**

| Parameter | Value        | Description                     |
| --------- | ------------ | ------------------------------- |
| » type    | GOOGLE\_AUTH | Google Authenticator TOTP       |
| » type    | MAGIC\_LINK  | Magic link email verification   |
| » type    | PASSKEY      | WebAuthn passkey authentication |


# post\_mfa\_setup

`POST /mfa/setup`

*Setup MFA Method*

Initialize the setup process for a multi-factor authentication method. This endpoint prepares the MFA setup and returns the necessary configuration data.

#### TypeScript Client Library

```typescript
// Note: This endpoint doesn't have a direct client method in the provided TypeScript client
// You would need to use the generic makeRequest method:
// this.makeRequest<any>('mfa/setup', 'POST', {
//   mfaType: 'GOOGLE_AUTH',
//   email: 'user@example.com',
//   deviceInfo: { name: 'iPhone 12', type: 'mobile' }
// });
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/mfa/setup \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -d '{
    "mfaType": "GOOGLE_AUTH",
    "email": "user@example.com",
    "deviceInfo": {
      "name": "iPhone 12",
      "type": "mobile"
    }
  }'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/mfa/setup HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access-token}

{
  "mfaType": "GOOGLE_AUTH",
  "email": "user@example.com",
  "deviceInfo": {
    "name": "iPhone 12",
    "type": "mobile"
  }
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "mfaType": "GOOGLE_AUTH",
  "email": "user@example.com",
  "deviceInfo": {
    "name": "iPhone 12",
    "type": "mobile"
  }
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/mfa/setup',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/mfa/setup',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/mfa/setup', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array(
    'mfaType' => 'GOOGLE_AUTH',
    'email' => 'user@example.com',
    'deviceInfo' => array(
        'name' => 'iPhone 12',
        'type' => 'mobile'
    )
);

try {
    $response = $client->request('POST','https://backend.flashback.tech/mfa/setup', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/mfa/setup");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
con.setDoOutput(true);

String jsonInputString = "{\"mfaType\":\"GOOGLE_AUTH\",\"email\":\"user@example.com\",\"deviceInfo\":{\"name\":\"iPhone 12\",\"type\":\"mobile\"}}";
try(OutputStream os = con.getOutputStream()) {
    byte[] input = jsonInputString.getBytes("utf-8");
    os.write(input, 0, input.length);
}

int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{`{"mfaType":"GOOGLE_AUTH","email":"user@example.com","deviceInfo":{"name":"iPhone 12","type":"mobile"}}`})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/mfa/setup", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

#### Request Body <a href="#post_mfa_setup-request-body" id="post_mfa_setup-request-body"></a>

| Name       | Type   | Required | Description                              |
| ---------- | ------ | -------- | ---------------------------------------- |
| mfaType    | string | true     | Type of MFA method to setup              |
| email      | string | false    | Email address (required for magic links) |
| deviceInfo | object | false    | Device information for passkeys          |

> Body parameter

```json
{
  "mfaType": "GOOGLE_AUTH",
  "email": "user@example.com",
  "deviceInfo": {
    "name": "iPhone 12",
    "type": "mobile"
  }
}
```

> Example responses

> 200 Response

```json
{
  "success": true,
  "data": {
    "secret": "JBSWY3DPEHPK3PXP",
    "qrCode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
    "backupCodes": ["123456", "789012", "345678"]
  }
}
```

> 400 Response

```json
{
  "success": false,
  "error": "Invalid MFA type specified"
}
```

> 500 Response

```json
{
  "success": false,
  "error": "Failed to setup MFA"
}
```

#### Responses <a href="#post_mfa_setup-responses" id="post_mfa_setup-responses"></a>

| Status | Meaning                                                                    | Description                      | Schema |
| ------ | -------------------------------------------------------------------------- | -------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | MFA setup initiated successfully | Inline |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)           | Invalid request parameters       | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error            | Inline |

#### Response Schema <a href="#post_mfa_setup-responseschema" id="post_mfa_setup-responseschema"></a>

Status Code **200**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » data    | object  | false    | none         | MFA setup configuration data            |

Status Code **400**

| Name      | Type    | Required | Restrictions | Description                                   |
| --------- | ------- | -------- | ------------ | --------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful       |
| » error   | string  | false    | none         | Error message describing the validation issue |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |

**Enumerated Values**

| Parameter | Value        | Description                     |
| --------- | ------------ | ------------------------------- |
| » mfaType | GOOGLE\_AUTH | Google Authenticator TOTP       |
| » mfaType | MAGIC\_LINK  | Magic link email verification   |
| » mfaType | PASSKEY      | WebAuthn passkey authentication |


# post\_\_mfa\_verify-setup

`POST /mfa/verify-setup`

*Verify MFA Setup*

Verify and complete the setup process for a multi-factor authentication method. This endpoint validates the user's setup verification and enables the MFA method upon successful verification.

#### TypeScript Client Library

```typescript
// Note: This endpoint doesn't have a direct client method in the provided TypeScript client
// You would need to use the generic makeRequest method:
// this.makeRequest<any>('mfa/verify-setup', 'POST', {
//   mfaType: 'GOOGLE_AUTH',
//   code: '123456'
// });
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/mfa/verify-setup \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -d '{
    "mfaType": "GOOGLE_AUTH",
    "code": "123456"
  }'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/mfa/verify-setup HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access-token}

{
  "mfaType": "GOOGLE_AUTH",
  "code": "123456"
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "mfaType": "GOOGLE_AUTH",
  "code": "123456"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/mfa/verify-setup',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/mfa/verify-setup',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/mfa/verify-setup', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array(
    'mfaType' => 'GOOGLE_AUTH',
    'code' => '123456'
);

try {
    $response = $client->request('POST','https://backend.flashback.tech/mfa/verify-setup', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/mfa/verify-setup");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
con.setDoOutput(true);

String jsonInputString = "{\"mfaType\":\"GOOGLE_AUTH\",\"code\":\"123456\"}";
try(OutputStream os = con.getOutputStream()) {
    byte[] input = jsonInputString.getBytes("utf-8");
    os.write(input, 0, input.length);
}

int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{`{"mfaType":"GOOGLE_AUTH","code":"123456"}`})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/mfa/verify-setup", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

#### Request Body <a href="#post__mfa_verify-status-request-body" id="post__mfa_verify-status-request-body"></a>

| Name       | Type   | Required | Description                         |
| ---------- | ------ | -------- | ----------------------------------- |
| mfaType    | string | true     | Type of MFA method to verify        |
| code       | string | false    | Verification code (for Google Auth) |
| credential | object | false    | Passkey credential (for passkeys)   |

> Body parameter

```json
{
  "mfaType": "GOOGLE_AUTH",
  "code": "123456"
}
```

> Example responses

> 200 Response

```json
{
  "success": true,
  "message": "MFA setup verified and enabled"
}
```

> 400 Response

```json
{
  "success": false,
  "error": "MFA setup verification failed"
}
```

> 500 Response

```json
{
  "success": false,
  "error": "Failed to verify MFA setup"
}
```

#### Responses <a href="#post__mfa_verify-status-responses" id="post__mfa_verify-status-responses"></a>

| Status | Meaning                                                                    | Description                     | Schema |
| ------ | -------------------------------------------------------------------------- | ------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | MFA setup verified successfully | Inline |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)           | Verification failed             | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error           | Inline |

#### Response Schema <a href="#post__mfa_verify-status-responseschema" id="post__mfa_verify-status-responseschema"></a>

Status Code **200**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Success message confirming verification |

Status Code **400**

| Name      | Type    | Required | Restrictions | Description                                       |
| --------- | ------- | -------- | ------------ | ------------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful           |
| » error   | string  | false    | none         | Error message describing the verification failure |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |

**Enumerated Values**

| Parameter | Value        | Description                     |
| --------- | ------------ | ------------------------------- |
| » mfaType | GOOGLE\_AUTH | Google Authenticator TOTP       |
| » mfaType | MAGIC\_LINK  | Magic link email verification   |
| » mfaType | PASSKEY      | WebAuthn passkey authentication |


# post\_\_mfa\_enable

`POST /mfa/enable`

*Enable MFA Method*

Enable a previously configured multi-factor authentication method for the authenticated user.

#### TypeScript Client Library

```typescript
// Note: This endpoint doesn't have a direct client method in the provided TypeScript client
// You would need to use the generic makeRequest method:
// this.makeRequest<any>('mfa/enable', 'POST', { mfaType: 'GOOGLE_AUTH' });
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/mfa/enable \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -d '{
    "mfaType": "GOOGLE_AUTH"
  }'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/mfa/enable HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access-token}

{
  "mfaType": "GOOGLE_AUTH"
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "mfaType": "GOOGLE_AUTH"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/mfa/enable',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/mfa/enable',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/mfa/enable', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array(
    'mfaType' => 'GOOGLE_AUTH'
);

try {
    $response = $client->request('POST','https://backend.flashback.tech/mfa/enable', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/mfa/enable");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
con.setDoOutput(true);

String jsonInputString = "{\"mfaType\":\"GOOGLE_AUTH\"}";
try(OutputStream os = con.getOutputStream()) {
    byte[] input = jsonInputString.getBytes("utf-8");
    os.write(input, 0, input.length);
}

int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{`{"mfaType":"GOOGLE_AUTH"}`})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/mfa/enable", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

#### Request Body <a href="#post__mfa_enabled-request-body" id="post__mfa_enabled-request-body"></a>

| Name    | Type   | Required | Description                  |
| ------- | ------ | -------- | ---------------------------- |
| mfaType | string | true     | Type of MFA method to enable |

> Body parameter

```json
{
  "mfaType": "GOOGLE_AUTH"
}
```

> Example responses

> 200 Response

```json
{
  "success": true,
  "message": "MFA method enabled"
}
```

> 500 Response

```json
{
  "success": false,
  "error": "Failed to enable MFA"
}
```

#### Responses <a href="#post__mfa_enabled-responses" id="post__mfa_enabled-responses"></a>

| Status | Meaning                                                                    | Description                     | Schema |
| ------ | -------------------------------------------------------------------------- | ------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | MFA method enabled successfully | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error           | Inline |

#### Response Schema <a href="#post__mfa_enabled-responseschema" id="post__mfa_enabled-responseschema"></a>

Status Code **200**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Success message confirming the action   |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |

**Enumerated Values**

| Parameter | Value        | Description                     |
| --------- | ------------ | ------------------------------- |
| » mfaType | GOOGLE\_AUTH | Google Authenticator TOTP       |
| » mfaType | MAGIC\_LINK  | Magic link email verification   |
| » mfaType | PASSKEY      | WebAuthn passkey authentication |


# post\_mfa\_disable

`POST /mfa/disable`

*Disable MFA Method*

Disable a previously enabled multi-factor authentication method for the authenticated user. This action may be restricted if MFA is enforced by the organization.

#### TypeScript Client Library

```typescript
// Note: This endpoint doesn't have a direct client method in the provided TypeScript client
// You would need to use the generic makeRequest method:
// this.makeRequest<any>('mfa/disable', 'POST', { mfaType: 'GOOGLE_AUTH' });
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/mfa/disable \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -d '{
    "mfaType": "GOOGLE_AUTH"
  }'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/mfa/disable HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access-token}

{
  "mfaType": "GOOGLE_AUTH"
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "mfaType": "GOOGLE_AUTH"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/mfa/disable',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/mfa/disable',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/mfa/disable', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array(
    'mfaType' => 'GOOGLE_AUTH'
);

try {
    $response = $client->request('POST','https://backend.flashback.tech/mfa/disable', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/mfa/disable");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
con.setDoOutput(true);

String jsonInputString = "{\"mfaType\":\"GOOGLE_AUTH\"}";
try(OutputStream os = con.getOutputStream()) {
    byte[] input = jsonInputString.getBytes("utf-8");
    os.write(input, 0, input.length);
}

int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{`{"mfaType":"GOOGLE_AUTH"}`})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/mfa/disable", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

#### Request Body <a href="#post_mfa_disable-request-body" id="post_mfa_disable-request-body"></a>

| Name    | Type   | Required | Description                   |
| ------- | ------ | -------- | ----------------------------- |
| mfaType | string | true     | Type of MFA method to disable |

> Body parameter

```json
{
  "mfaType": "GOOGLE_AUTH"
}
```

> Example responses

> 200 Response

```json
{
  "success": true,
  "message": "MFA method disabled"
}
```

> 403 Response

```json
{
  "success": false,
  "error": "Cannot disable MFA when enforced by organization"
}
```

> 500 Response

```json
{
  "success": false,
  "error": "Failed to disable MFA"
}
```

#### Responses <a href="#post_mfa_disable-responses" id="post_mfa_disable-responses"></a>

| Status | Meaning                                                                    | Description                                       | Schema |
| ------ | -------------------------------------------------------------------------- | ------------------------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | MFA method disabled successfully                  | Inline |
| 403    | [Forbidden](https://tools.ietf.org/html/rfc7231#section-6.5.3)             | MFA cannot be disabled due to organization policy | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error                             | Inline |

#### Response Schema <a href="#post_mfa_disable-responseschema" id="post_mfa_disable-responseschema"></a>

Status Code **200**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Success message confirming the action   |

Status Code **403**

| Name      | Type    | Required | Restrictions | Description                              |
| --------- | ------- | -------- | ------------ | ---------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful  |
| » error   | string  | false    | none         | Error message describing the restriction |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |

**Enumerated Values**

| Parameter | Value        | Description                     |
| --------- | ------------ | ------------------------------- |
| » mfaType | GOOGLE\_AUTH | Google Authenticator TOTP       |
| » mfaType | MAGIC\_LINK  | Magic link email verification   |
| » mfaType | PASSKEY      | WebAuthn passkey authentication |


# post\_\_mfa\_primary

`POST /mfa/primary`

*Set Primary MFA Method*

Set the primary multi-factor authentication method for the authenticated user. The primary method will be used as the default when multiple MFA methods are available.

#### TypeScript Client Library

```typescript
// Note: This endpoint doesn't have a direct client method in the provided TypeScript client
// You would need to use the generic makeRequest method:
// this.makeRequest<any>('mfa/primary', 'POST', { mfaType: 'GOOGLE_AUTH' });
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/mfa/primary \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -d '{
    "mfaType": "GOOGLE_AUTH"
  }'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/mfa/primary HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access-token}

{
  "mfaType": "GOOGLE_AUTH"
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "mfaType": "GOOGLE_AUTH"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/mfa/primary',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/mfa/primary',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/mfa/primary', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array(
    'mfaType' => 'GOOGLE_AUTH'
);

try {
    $response = $client->request('POST','https://backend.flashback.tech/mfa/primary', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/mfa/primary");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
con.setDoOutput(true);

String jsonInputString = "{\"mfaType\":\"GOOGLE_AUTH\"}";
try(OutputStream os = con.getOutputStream()) {
    byte[] input = jsonInputString.getBytes("utf-8");
    os.write(input, 0, input.length);
}

int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{`{"mfaType":"GOOGLE_AUTH"}`})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/mfa/primary", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

#### Request Body <a href="#post__mfa_primary-request-body" id="post__mfa_primary-request-body"></a>

| Name    | Type   | Required | Description                          |
| ------- | ------ | -------- | ------------------------------------ |
| mfaType | string | true     | Type of MFA method to set as primary |

> Body parameter

```json
{
  "mfaType": "GOOGLE_AUTH"
}
```

> Example responses

> 200 Response

```json
{
  "success": true,
  "message": "Primary MFA method updated"
}
```

> 500 Response

```json
{
  "success": false,
  "error": "Failed to set primary MFA"
}
```

#### Responses <a href="#post__mfa_primary-responses" id="post__mfa_primary-responses"></a>

| Status | Meaning                                                                    | Description                             | Schema |
| ------ | -------------------------------------------------------------------------- | --------------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | Primary MFA method updated successfully | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error                   | Inline |

#### Response Schema <a href="#post__mfa_primary-responseschema" id="post__mfa_primary-responseschema"></a>

Status Code **200**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Success message confirming the action   |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |

**Enumerated Values**

| Parameter | Value        | Description                     |
| --------- | ------------ | ------------------------------- |
| » mfaType | GOOGLE\_AUTH | Google Authenticator TOTP       |
| » mfaType | MAGIC\_LINK  | Magic link email verification   |
| » mfaType | PASSKEY      | WebAuthn passkey authentication |


# post\_\_mfa\_organization\_enforce

`POST /mfa/organization/enforce`

*Enforce Organization MFA Policy*

Update the multi-factor authentication enforcement policy for the organization. This endpoint allows administrators to require MFA for all organization members.

#### TypeScript Client Library

```typescript
// Note: This endpoint doesn't have a direct client method in the provided TypeScript client
// You would need to use the generic makeRequest method:
// this.makeRequest<any>('mfa/organization/enforce', 'POST', { enforced: true });
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/mfa/organization/enforce \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -d '{
    "enforced": true
  }'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/mfa/organization/enforce HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access-token}

{
  "enforced": true
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const inputBody = '{
  "enforced": true
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/mfa/organization/enforce',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/mfa/organization/enforce',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/mfa/organization/enforce', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array(
    'enforced' => true
);

try {
    $response = $client->request('POST','https://backend.flashback.tech/mfa/organization/enforce', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/mfa/organization/enforce");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
con.setDoOutput(true);

String jsonInputString = "{\"enforced\":true}";
try(OutputStream os = con.getOutputStream()) {
    byte[] input = jsonInputString.getBytes("utf-8");
    os.write(input, 0, input.length);
}

int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{`{"enforced":true}`})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/mfa/organization/enforce", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

#### Request Body <a href="#post__mfa_organization_enforce-request-body" id="post__mfa_organization_enforce-request-body"></a>

| Name     | Type    | Required | Description                                         |
| -------- | ------- | -------- | --------------------------------------------------- |
| enforced | boolean | true     | Whether MFA should be enforced for the organization |

> Body parameter

```json
{
  "enforced": true
}
```

> Example responses

> 200 Response

```json
{
  "success": true,
  "message": "MFA enforcement enabled for organization"
}
```

> 400 Response

```json
{
  "success": false,
  "error": "User not associated with an organization"
}
```

> 500 Response

```json
{
  "success": false,
  "error": "Failed to update organization MFA enforcement"
}
```

#### Responses <a href="#post__mfa_organization_enforce-responses" id="post__mfa_organization_enforce-responses"></a>

| Status | Meaning                                                                    | Description                          | Schema |
| ------ | -------------------------------------------------------------------------- | ------------------------------------ | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | MFA enforcement updated successfully | Inline |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)           | Invalid request parameters           | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error                | Inline |

#### Response Schema <a href="#post__mfa_organization_enforce-responseschema" id="post__mfa_organization_enforce-responseschema"></a>

Status Code **200**

| Name      | Type    | Required | Restrictions | Description                                  |
| --------- | ------- | -------- | ------------ | -------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful      |
| » message | string  | false    | none         | Success message confirming the policy update |

Status Code **400**

| Name      | Type    | Required | Restrictions | Description                                   |
| --------- | ------- | -------- | ------------ | --------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful       |
| » error   | string  | false    | none         | Error message describing the validation issue |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |


# post\_\_mfa\_reset

`POST /mfa/reset`

*Reset MFA Configuration*

Reset the user's multi-factor authentication configuration. This endpoint allows users to reset their MFA setup when they lose access to their MFA methods. Organization owners and administrators can also reset MFA settings for other users in their organization.

#### Request Body

| Name        | Type   | Required | Description                                                                                                                    |
| ----------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| resetUserId | string | false    | Optional user ID to reset MFA for. If not provided, resets the authenticated user's MFA. Requires OWNER or ADMINISTRATOR role. |

#### TypeScript Client Library

```typescript
// Note: This endpoint doesn't have a direct client method in the provided TypeScript client
// You would need to use the generic makeRequest method:
// For self-reset:
// this.makeRequest<any>('mfa/reset', 'POST', null);
// For admin reset:
// this.makeRequest<any>('mfa/reset', 'POST', { resetUserId: 'user-id' });
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# Self-reset (reset your own MFA)
curl -X POST https://backend.flashback.tech/mfa/reset \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'

# Admin reset (reset another user's MFA - requires OWNER or ADMINISTRATOR role)
curl -X POST https://backend.flashback.tech/mfa/reset \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -H 'Content-Type: application/json' \
  -d '{"resetUserId": "user-id-to-reset"}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
# Self-reset
POST https://backend.flashback.tech/mfa/reset HTTP/1.1
Host: localhost:3000
Accept: application/json
Authorization: Bearer {access-token}

# Admin reset
POST https://backend.flashback.tech/mfa/reset HTTP/1.1
Host: localhost:3000
Accept: application/json
Authorization: Bearer {access-token}
Content-Type: application/json

{"resetUserId": "user-id-to-reset"}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
// Self-reset
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/mfa/reset',
{
  method: 'POST',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

// Admin reset
const adminHeaders = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}',
  'Content-Type':'application/json'
};

const body = JSON.stringify({
  resetUserId: 'user-id-to-reset'
});

fetch('https://backend.flashback.tech/mfa/reset',
{
  method: 'POST',
  headers: adminHeaders,
  body: body
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

# Self-reset
headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/mfa/reset',
  params: {
  }, headers: headers

p JSON.parse(result)

# Admin reset
admin_headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}',
  'Content-Type' => 'application/json'
}

body = {
  resetUserId: 'user-id-to-reset'
}.to_json

result = RestClient.post 'https://backend.flashback.tech/mfa/reset',
  body, headers: admin_headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
import json

# Self-reset
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/mfa/reset', headers = headers)
print(r.json())

# Admin reset
admin_headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}',
  'Content-Type': 'application/json'
}

data = {
  'resetUserId': 'user-id-to-reset'
}

r = requests.post('https://backend.flashback.tech/mfa/reset',
                 headers = admin_headers,
                 data = json.dumps(data))
print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

// Self-reset
$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

try {
    $response = $client->request('POST','https://backend.flashback.tech/mfa/reset', array(
        'headers' => $headers,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

// Admin reset
$admin_headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
    'Content-Type' => 'application/json',
);

$body = json_encode(array(
    'resetUserId' => 'user-id-to-reset'
));

try {
    $response = $client->request('POST','https://backend.flashback.tech/mfa/reset', array(
        'headers' => $admin_headers,
        'body' => $body
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
// Self-reset
URL obj = new URL("https://backend.flashback.tech/mfa/reset");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

// Admin reset
URL adminObj = new URL("https://backend.flashback.tech/mfa/reset");
HttpURLConnection adminCon = (HttpURLConnection) adminObj.openConnection();
adminCon.setRequestMethod("POST");
adminCon.setRequestProperty("Accept", "application/json");
adminCon.setRequestProperty("Authorization", "Bearer {access-token}");
adminCon.setRequestProperty("Content-Type", "application/json");
adminCon.setDoOutput(true);

String jsonInputString = "{\"resetUserId\": \"user-id-to-reset\"}";
try(OutputStream os = adminCon.getOutputStream()) {
    byte[] input = jsonInputString.getBytes("utf-8");
    os.write(input, 0, input.length);
}

int adminResponseCode = adminCon.getResponseCode();
BufferedReader adminIn = new BufferedReader(
    new InputStreamReader(adminCon.getInputStream()));
String adminInputLine;
StringBuffer adminResponse = new StringBuffer();
while ((adminInputLine = adminIn.readLine()) != null) {
    adminResponse.append(adminInputLine);
}
adminIn.close();
System.out.println(adminResponse.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
       "encoding/json"
)

func main() {
    // Self-reset
    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/mfa/reset", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...

    // Admin reset
    adminHeaders := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
        "Content-Type": []string{"application/json"},
    }

    requestBody := map[string]string{
        "resetUserId": "user-id-to-reset",
    }
    jsonData, _ := json.Marshal(requestBody)

    adminData := bytes.NewBuffer(jsonData)
    adminReq, err := http.NewRequest("POST", "https://backend.flashback.tech/mfa/reset", adminData)
    adminReq.Header = adminHeaders

    adminResp, err := client.Do(adminReq)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Example responses

> 200 Response

```json
{
  "success": true,
  "message": "MFA reset successfully"
}
```

> 403 Response

```json
{
  "success": false,
  "error": "Insufficient permissions. OWNER or ADMINISTRATOR role required to reset another user's MFA."
}
```

> 404 Response

```json
{
  "success": false,
  "error": "User not found"
}
```

> 500 Response

```json
{
  "success": false,
  "error": "Failed to reset MFA"
}
```

#### Responses <a href="#post__mfa_reset-responses" id="post__mfa_reset-responses"></a>

| Status | Meaning                                                                    | Description                                          | Schema |
| ------ | -------------------------------------------------------------------------- | ---------------------------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | MFA reset completed successfully                     | Inline |
| 403    | [Forbidden](https://tools.ietf.org/html/rfc7231#section-6.5.3)             | Insufficient permissions to reset another user's MFA | Inline |
| 404    | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)             | User not found                                       | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error                                | Inline |

#### Response Schema <a href="#post__mfa_reset-responseschema" id="post__mfa_reset-responseschema"></a>

Status Code **200**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » message | string  | false    | none         | Success message confirming the reset    |

Status Code **403**

| Name      | Type    | Required | Restrictions | Description                                   |
| --------- | ------- | -------- | ------------ | --------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful       |
| » error   | string  | false    | none         | Error message describing the permission issue |

Status Code **404**

| Name      | Type    | Required | Restrictions | Description                                 |
| --------- | ------- | -------- | ------------ | ------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful     |
| » error   | string  | false    | none         | Error message describing the user not found |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |


# post\_\_mfa\_magic-link\_send

`POST /mfa/magic-link/send`

*Send Magic Link for MFA Verification*

Send a magic link to the user's email address for multi-factor authentication verification. The magic link will be sent to the email address associated with the authenticated user's account.

#### TypeScript Client Library

```typescript
// Note: This endpoint doesn't have a direct client method in the provided TypeScript client
// You would need to use the generic makeRequest method:
// this.makeRequest<any>('mfa/magic-link/send', 'POST', null);
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
# You can also use wget
curl -X POST https://backend.flashback.tech/mfa/magic-link/send \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/mfa/magic-link/send HTTP/1.1
Host: localhost:3000
Accept: application/json
Authorization: Bearer {access-token}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://backend.flashback.tech/mfa/magic-link/send',
{
  method: 'POST',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}'
}

result = RestClient.post 'https://backend.flashback.tech/mfa/magic-link/send',
  params: {
  }, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

r = requests.post('https://backend.flashback.tech/mfa/magic-link/send', headers = headers)

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

try {
    $response = $client->request('POST','https://backend.flashback.tech/mfa/magic-link/send', array(
        'headers' => $headers,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/mfa/magic-link/send");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
    }

    data := bytes.NewBuffer([]byte{})
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/mfa/magic-link/send", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Example responses

> 200 Response

```json
{
  "success": true,
  "message": "Magic link sent successfully"
}
```

> 404 Response

```json
{
  "success": false,
  "error": "User not found"
}
```

> 500 Response

```json
{
  "success": false,
  "error": "Failed to send magic link"
}
```

#### Responses <a href="#post__mfa_magic-link_send-responses" id="post__mfa_magic-link_send-responses"></a>

| Status | Meaning                                                                    | Description                  | Schema |
| ------ | -------------------------------------------------------------------------- | ---------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | Magic link sent successfully | Inline |
| 404    | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)             | User not found               | Inline |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal server error        | Inline |

#### Response Schema <a href="#post__mfa_magic-link_send-responseschema" id="post__mfa_magic-link_send-responseschema"></a>

Status Code **200**

| Name      | Type    | Required | Restrictions | Description                                        |
| --------- | ------- | -------- | ------------ | -------------------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful            |
| » message | string  | false    | none         | Success message confirming the magic link was sent |

Status Code **404**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |

Status Code **500**

| Name      | Type    | Required | Restrictions | Description                             |
| --------- | ------- | -------- | ------------ | --------------------------------------- |
| » success | boolean | false    | none         | Indicates if the request was successful |
| » error   | string  | false    | none         | Error message describing the issue      |




---

[Next Page](/llms-full.txt/1)

