Skip to main content

Creating Your First Secret

Learn how to store sensitive credentials securely and inject them into backend requests without exposing them to clients.

What is a Secret?

A secret in KnoxCall is an encrypted credential (API key, password, token) that’s injected into your backend requests server-side. Your clients never see the actual value.

Why Use Secrets?

Without KnoxCall secrets:
// ❌ Frontend code - API key exposed in browser!
fetch("https://api.stripe.com/charges", {
  headers: {
    "Authorization": "Bearer sk_live_abc123xyz789..."
  }
});
Anyone with dev tools can see your Stripe key! 😱 With KnoxCall secrets:
// ✅ Frontend code - No secrets exposed
fetch("https://a1b2c3d4.DunderMifflin.knoxcall.com/api/payments", {
  headers: {
    "x-knoxcall-key": "tk_abc123...",
    "x-knoxcall-route": "stripe-payments"
  }
});
KnoxCall injects your Stripe key server-side:
Client Request → KnoxCall → Adds "Authorization: Bearer sk_live_abc..." → Stripe API
Your secret stays secure on KnoxCall’s servers! 🔐

Secret Types

KnoxCall supports two types of secrets:

1. String Secrets (Most Common)

Simple encrypted values:
  • API keys (Stripe, SendGrid, Twilio)
  • Passwords (database, services)
  • Tokens (auth tokens, webhook secrets)
  • Any sensitive string value

2. OAuth2 Secrets (Advanced)

Full OAuth2 flow with automatic token refresh:
  • Google OAuth tokens (auto-refreshes when expired)
  • Shopify, HubSpot, Microsoft, Slack OAuth
  • Stores access token, refresh token, and expiry
  • Handles token rotation automatically
We’ll focus on string secrets in this guide.

How Secrets Work

1. You create secret in KnoxCall UI

2. Value encrypted with AES-256-GCM

3. Stored securely in encrypted vault

4. You reference secret in route config: {{secret:stripe_key}}

5. Client makes request through KnoxCall

6. KnoxCall decrypts secret server-side

7. Injects decrypted value into backend request

8. Backend receives request with actual API key

9. Client never sees the secret value!
Encryption: AES-256-GCM with envelope encryption (same security as AWS, Google Cloud)

Create Your First Secret

Step 1: Navigate to Secrets

  1. Click Resources in the sidebar
  2. Select Secrets
  3. Click Add Secret

Step 2: Choose Secret Type

Select String Secret (for this guide)

Step 3: Fill in Details

Secret Name:
stripe_prod_key
Lowercase with underscores. This is how you’ll reference it in templates. Secret Value:
sk_live_abc123xyz789def456ghi789jkl012
Paste your actual Stripe API key Description (optional but recommended):
Stripe production API key - expires Dec 2025
Tags (optional):
production, payment, stripe

Step 4: Save

Click Create Secret The value is immediately encrypted using AES-256-GCM. You’ll never see the plaintext value again in the UI!
Copy your secret value elsewhere if you need it! Once saved, KnoxCall only shows encrypted form. The plaintext cannot be retrieved (only used in requests).

Use Secret in a Route

Now let’s inject your secret into backend requests.

Step 1: Edit Your Route

  1. Navigate to Routes
  2. Click your route (e.g., “stripe-payments”)
  3. Click Edit

Step 2: Inject Secret in Headers

Find the Inject Headers section and add:
{
  "Authorization": "Bearer {{secret:stripe_prod_key}}"
}
Template syntax: {{secret:name}}
  • secret: is required prefix
  • name is your secret name (e.g., stripe_prod_key)
Common header patterns: Bearer token:
{
  "Authorization": "Bearer {{secret:api_key}}"
}
API key header:
{
  "X-API-Key": "{{secret:sendgrid_key}}"
}
Basic auth:
{
  "Authorization": "Basic {{secret:base64_credentials}}"
}
Custom header:
{
  "X-Webhook-Secret": "{{secret:webhook_secret}}",
  "X-App-ID": "{{secret:app_id}}"
}

Step 3: Or Inject Secret in Body

For POST/PUT/PATCH requests, inject into JSON body:
{
  "api_key": "{{secret:printnode_key}}",
  "computerId": 123,
  "options": {
    "auth_token": "{{secret:auth_token}}"
  }
}
Secrets work in nested objects too!

Step 4: Save Route

Click Save Changes

Test Your Secret

Make a Request

curl -X POST "https://a1b2c3d4.DunderMifflin.knoxcall.com/api/charge" \
  -H "x-knoxcall-key: tk_abc123..." \
  -H "x-knoxcall-route: stripe-payments" \
  -H "Content-Type: application/json" \
  -d '{"amount": 1000, "currency": "usd"}'

What Happens

  1. KnoxCall receives your request
  2. Loads route “stripe-payments”
  3. Sees {{secret:stripe_prod_key}} in header template
  4. Decrypts secret server-side
  5. Replaces template with actual value:
    Authorization: Bearer sk_live_abc123xyz789...
    
  6. Forwards request to Stripe API with real key
  7. Returns response to you
Your client never saw the Stripe key!

View in Logs

  1. Navigate to LogsAPI Logs
  2. Find your request
  3. Click to expand details
  4. Notice: Request headers show {{secret:stripe_prod_key}} (template)
  5. But backend received actual decrypted value
Logs never expose plaintext secret values for security.

Multiple Secrets in One Route

You can use multiple secrets in a single route:
{
  "Authorization": "Bearer {{secret:stripe_key}}",
  "X-Webhook-Secret": "{{secret:webhook_secret}}",
  "X-User-ID": "{{secret:user_id}}"
}
Or in body:
{
  "payment_key": "{{secret:stripe_key}}",
  "notification_key": "{{secret:twilio_key}}",
  "database_url": "{{secret:postgres_url}}"
}
All secrets are decrypted and injected in a single pass.

Environment-Specific Secrets

Use different secrets per environment (dev/staging/prod):

Create Environment-Specific Secrets

  1. Development:
    • Name: stripe_dev_key
    • Value: sk_test_abc123...
  2. Staging:
    • Name: stripe_staging_key
    • Value: sk_test_xyz789...
  3. Production:
    • Name: stripe_prod_key
    • Value: sk_live_abc123...

Configure Route Per Environment

Base route (production):
{
  "Authorization": "Bearer {{secret:stripe_prod_key}}"
}
Development override:
{
  "Authorization": "Bearer {{secret:stripe_dev_key}}"
}
Staging override:
{
  "Authorization": "Bearer {{secret:stripe_staging_key}}"
}
Now each environment uses its own Stripe key automatically!

Secret Versioning

KnoxCall tracks secret versions for rollback:

Rotate a Secret

  1. Navigate to Secrets
  2. Click your secret (e.g., “stripe_prod_key”)
  3. Click Add New Version
  4. Enter new value:
    sk_live_new789xyz123abc456def789
    
  5. Save
What happens:
  • New version becomes active immediately
  • Old version preserved (for rollback if needed)
  • All routes using this secret now use new value
  • Zero downtime! No code changes needed

View Version History

  1. Open secret details
  2. Click Version History tab
  3. See all versions with timestamps
  4. Can rollback to previous version if needed

Common Use Cases

Payment APIs

{
  "Authorization": "Bearer {{secret:stripe_prod_key}}"
}
{
  "Authorization": "Bearer {{secret:paypal_access_token}}"
}

Email/SMS Services

{
  "Authorization": "Bearer {{secret:sendgrid_api_key}}"
}
{
  "X-API-Key": "{{secret:twilio_auth_token}}"
}

Webhooks

{
  "X-Webhook-Secret": "{{secret:github_webhook_secret}}"
}
{
  "X-Signature": "{{secret:shopify_hmac_secret}}"
}

Database Credentials

{
  "db_url": "{{secret:postgres_connection_string}}"
}

Printing Services

{
  "Authorization": "Basic {{secret:printnode_api_key}}"
}

Security Best Practices

Naming Conventions

Good names:
stripe_prod_key
sendgrid_dev_api_key
database_password_production
github_webhook_secret_staging
Bad names:
secret1
key
password
temp
Use descriptive names that indicate:
  • Service (stripe, sendgrid)
  • Purpose (api_key, webhook_secret)
  • Environment (prod, staging, dev)

Secret Rotation

Recommended rotation schedule:
  • Critical secrets (payment APIs): Every 90 days
  • Less critical: Every 180 days
  • Development: Annually
How to rotate:
  1. Generate new key in third-party service (Stripe, etc.)
  2. Create new version in KnoxCall
  3. Test in staging first
  4. Deploy to production
  5. Wait 24-48 hours
  6. Revoke old key in third-party service

Separation by Environment

Do:
  • Different secrets for dev/staging/prod
  • Never use prod secrets in development
  • Test secret rotation in staging first
Don’t:
  • Reuse production secrets in development
  • Share secrets across unrelated services
  • Commit secrets to git (even encrypted)

Access Control

  • Only give team members access to secrets they need
  • Use least privilege principle
  • Audit secret access regularly
  • Delete unused secrets promptly

Monitoring

  • Set up alerts for failed secret decryption
  • Monitor secret usage in logs
  • Track secret rotation dates
  • Get notified when secrets expire

Troubleshooting

Secret Not Found Error

Error: Secret 'stripe_key' not found Causes:
  • Typo in secret name
  • Secret was deleted
  • Wrong syntax (forgot secret: prefix)
Fix:
  1. Check secret exists: Secrets page
  2. Verify name spelling matches exactly
  3. Check template syntax: {{secret:name}} (not {{name}})

Template Not Replaced

Symptoms: Backend receives literal {{secret:stripe_key}} instead of actual value Causes:
  • Wrong template syntax
  • Secret referenced but not found
  • Header injection disabled
Debug:
  1. Check logs - see what was actually sent
  2. Verify template syntax is correct
  3. Test secret exists and name matches
  4. Check inject headers is enabled

Wrong Value Injected

Symptoms: Backend gets wrong API key Causes:
  • Using wrong environment
  • Secret not configured for environment
  • Old version being used
Fix:
  1. Check which environment request used
  2. Verify secret configured for that environment
  3. Check secret version (maybe need to create new version)
  4. Look at logs to see which value was injected

Next Steps

Now that you understand secrets:
  • Secret Versioning: Track changes and rollback if needed
  • Environment Overrides: Different secrets per dev/staging/prod
  • Template System: {{secret:name}} syntax for injection
  • Encryption: AES-256-GCM with envelope encryption
  • OAuth2 Secrets: Automatic token refresh for OAuth flows

📊 Statistics

  • Level: beginner
  • Time: 10 minutes

🏷️ Tags

secrets, security, credentials, encryption, quickstart