Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.userepo.com/llms.txt

Use this file to discover all available pages before exploring further.

Every API key carries two scope dimensions:
  1. Allowed actions — what verbs the key can perform (search, ask, ingest, etc.)
  2. Allowed providers — which data sources the key can retrieve from (slack, notion, etc.)
Both are enforced server-side. A scoped key cannot bypass its restrictions by crafting a clever request — the filtering happens before any data leaves the database.

Why scope agents narrowly

The agent you ship to production is almost certainly not allowed to do everything you, the developer, can do in the console. A customer-support agent reading Slack #support is a different blast radius than an admin script that can mint new keys. The pattern:
  • Admin key — Lives in your secrets manager. Used by your backend to mint per-agent keys.
  • Per-agent keys — One key per logical agent, scoped to the narrowest set of actions + providers it actually needs.
If a key leaks, you revoke that one key. The blast radius is the scope of that single agent.

Action scoping

When you call /v1/api-keys (POST) to create a key, pass allowedActions as an array. Repo rejects requests for any action not in the list:
# Key created with allowedActions: ["search", "context"]
# This will fail with 403:
curl -X POST https://api.userepo.com/v1/ask \
  -H "Authorization: Bearer repo_scoped_key" \
  -d '{"query": "..."}'

# Response:
# {"error":"API key not allowed to perform 'ask' action"}

Provider scoping

allowedProviders is an optional array of provider IDs. null means “no restriction” — the key sees everything the org has connected. An array means “only these providers.”
// Key restricted to Slack + Notion
{
  "allowedProviders": ["slack", "notion"]
}
When the key calls /v1/search or /v1/context:
  1. The retrieval query runs against the full org index.
  2. Hits from excluded providers are filtered out before serialization.
  3. The response includes an exclusions array explaining which providers were filtered and why — so your agent knows the data exists but it wasn’t allowed to see it.
{
  "exclusions": [
    {
      "type": "provider_scope",
      "provider": "gmail",
      "reason": "The authenticating API key is not allowed to retrieve this provider."
    }
  ]
}
This is critical for honest agent behavior: the agent can tell its user “I have additional context I’m not allowed to share” instead of pretending the data doesn’t exist.

Source-level access policies

Beyond key scopes, individual source items carry their own accessPolicy metadata captured at ingest time. Examples:
  • Notion: mode: "provider_scope" — the integration grants per-page access; retrieval is governed by what the integration was given.
  • Google Drive: mode: "source_acl" — each file carries its sharing settings; Repo preserves them and can re-enforce on retrieval.
  • Gmail: mode: "provider_scope" — mailbox-level access; bound to the OAuth grant.
  • Slack: mode: "channel_scope" — limited to channels the bot was added to + the channel allowlist.
Future work: /v1/context will support an actingAsUserId parameter so an agent representing a specific human can be further scoped to only that human’s accessible sources. This is on the roadmap and not yet live.