API keys & encryption setup

From dashboard sign-in to events flowing, and what's happening under the hood at each step.

4 min read · verified against [email protected]

Connecting an application to Guard Core takes eight steps. The first six happen in the dashboard. The last two happen in your app. Once you know where things live, the whole flow takes about five minutes.

The flow, end to end

StepSurfaceWhat you do
1DashboardSign in at app.guard-core.com
2DashboardCreate or open a Project (or use the Demo project)
3DashboardCopy the Project ID - format proj_ + 16 alphanumeric chars
4DashboardOpen API Keys (from the project page link, or Settings → API Keys)
5DashboardCreate a key. Enable encryption (recommended).
6DashboardCopy both credentials - shown ONCE, no recovery path
7Your appInstall the adapter + telemetry agent: pip install fastapi-guard guard-agent (or uv add fastapi-guard guard-agent)
8Your appPaste into SecurityConfig in app.py, then restart. Events start flowing.

What a project is

A project is the scoping unit for everything Guard Core does. Events, metrics, threats, rules, and API keys are all scoped to a project. The common pattern is one app per project, but one project per team / service / environment also works.

For current per-tier limits and quotas, check Settings → Billing in the dashboard. They vary by plan and change.

Project ID format

Externally: proj_ prefix followed by 16 alphanumeric characters. Internally the project is a UUIDv7. The API accepts both forms for routing and scoping. They map to the same row.

What an API key actually is

At rest, the core stores only the SHA-256 hash of the key, never the plaintext. Verification uses a timing-safe comparison so a leaked database doesn't give an attacker usable keys.

Lifecycle: the plaintext exists in one HTTP response and nowhere else. Lost it? Revoke and create a new one. There's no recovery endpoint.

POST /api/v1/events
X-API-Key: fg_01He...
X-Project-Id: proj_abc123def456...

Encryption - AES-256-GCM, end to end

When you enable encryption at key-creation time, the project gets a second secret: a project encryption key. The agent uses it to seal every event before it leaves your process.

PropertyValue
AlgorithmAES-256-GCM (authenticated)
Nonce12 bytes, random per request
Authentication tag16 bytes
Transport encodingBase64
ScopeThe entire JSON event payload, not per-field
LayeringSits on top of TLS - useful when a TLS-terminating proxy is in the path
At restIf the project has an encryption key, ingested events are persisted encrypted

Project key lifecycle

  1. Created - random 32-byte value generated server-side, returned to you once (base64).
  2. Stored (server) - wrapped under a server-side master key.
  3. Held (client) - you set it as agent_project_encryption_key in SecurityConfig; the agent uses it to seal events.
  4. Rotation - call the rotation endpoint. The old wrapped key is replaced. Historical events stay decryptable because each ciphertext carries its own version marker; new events use the new version.

The ingest endpoints

The agent picks the right endpoint automatically based on your config.

EndpointUsed when
POST /api/v1/eventsNo project encryption key configured
POST /api/v1/events/encryptedagent_project_encryption_key is set
POST /api/v1/statusAgent heartbeat - liveness + buffer stats
POST /api/v1/metricsAggregated counters and timings

Wiring it into SecurityConfig

Dashboard value→SecurityConfig field
API key→agent_api_key
Project ID→agent_project_id
Encryption key (if enabled)→agent_project_encryption_key
Core URL→agent_endpoint (e.g., https://api.guard-core.com)
Turn on reporting→enable_agent=True
from fastapi import FastAPI
from guard import SecurityConfig, SecurityMiddleware
from guard.lifespan import guard_lifespan

security_config = SecurityConfig(
    enable_agent=True,
    agent_api_key=API_KEY,
    agent_project_id=PROJECT_ID,
    agent_endpoint="https://api.guard-core.com",
    agent_project_encryption_key=ENC_KEY,
    agent_buffer_size=5000,
    agent_flush_interval=2,
)

app = FastAPI(lifespan=guard_lifespan)
app.add_middleware(SecurityMiddleware, config=security_config)

Troubleshooting

SymptomLikely causeFix
Agent requests return 401Wrong key, revoked, or expiredRotate from the dashboard and update agent_api_key. The 401 response is timing-safe - same response for wrong vs missing.
No events showing in the dashboardenable_agent not True, agent_endpoint wrong, or agent_project_id belongs to a different project than the API keyVerify all three. Trigger a request and wait one agent_flush_interval.
Decryption errors on the core sideAgent key doesn't match the project's wrapped key, key rotation happened but agents weren't updated, or encryption was disabled after the agent was configuredPull the current key from the dashboard, or rotate again and update both sides together.