Skip to content

Agent bootstrap

This guide shows the full lifecycle:

  1. Human creates a provisioning key once
  2. Agent self-provisions a standard key at runtime
  3. Agent verifies emails with the standard key
  4. Agent checks usage before large jobs
sequenceDiagram
    participant H as Human
    participant D as Dashboard
    participant A as Agent
    participant M as truval.dev API

    H->>D: Create provisioning key in dashboard
    D-->>H: Key shown once, store securely

    A->>M: POST /v1/management/keys (Bearer mgmt key)
    M-->>A: Standard verify key, cache for reuse

    A->>M: POST /v1/email/verify (Bearer standard key)
    M-->>A: Verification JSON

    Note over A: Later runs reuse the cached standard key

(Provisioning keys use the sk_mgmt_… prefix; standard verify keys use sk_live_… or sk_test_… — omitted from the diagram so Mermaid does not treat underscores as italics.)

  • Create an account at dash.truval.dev
  • Create one provisioning key (sk_mgmt_...)
  • Store it in your runtime environment:
Terminal window
export TRUVAL_MGMT_KEY=sk_mgmt_...

On startup:

  • Try loading a cached standard key
  • If none exists, create one via POST /v1/management/keys
  • Cache the key in your agent state / secret store

Before large batches:

  • Call GET /v1/management/usage/summary
  • Compare calls_remaining with workload size

On the free tier, calls_remaining is monthly verification quota headroom (same rules as the verify API). On paid tiers, it reflects included billable allowance minus billable use. You can also call GET /v1/management/account and use limits.monthly_calls and usage_this_month on free for the same quota picture. Details: Management API (usage/summary and usage sections).

import { createClient, createManagementClient } from 'truval'
const mgmt = createManagementClient(process.env.TRUVAL_MGMT_KEY!)
let runtimeVerifyKey: string | null = null
async function getVerifyClient() {
if (!runtimeVerifyKey) {
const created = await mgmt.keys.create({ label: 'agent-runtime' })
runtimeVerifyKey = created.key
}
return createClient(runtimeVerifyKey)
}
export async function verifyOne(email: string) {
const client = await getVerifyClient()
return client.verify(email)
}
export async function verifyBatchSafely(emails: string[]) {
const usage = await mgmt.usage.summary()
if (usage.calls_remaining < emails.length) {
throw new Error(
`Insufficient remaining calls: need ${emails.length}, have ${usage.calls_remaining}`,
)
}
const client = await getVerifyClient()
return client.verifyBatch(emails)
}

4) MCP alternative (zero custom API wiring)

Section titled “4) MCP alternative (zero custom API wiring)”

Use truval.dev MCP with both headers:

{
"mcpServers": {
"truval": {
"url": "https://mcp.truval.dev/mcp",
"headers": {
"Authorization": "Bearer ${TRUVAL_API_KEY}",
"X-Truval-Provisioning-Key": "${TRUVAL_PROVISIONING_KEY}"
}
}
}
}

Then your agent can call:

  • create_api_key
  • list_api_keys
  • revoke_api_key
  • get_usage_summary
  • get_account
  • get_usage
  • create_billing_portal

without building raw HTTP wrappers.