Skip to main content

Migrate API Keys

Why Migrate

Embedding org API keys in client applications is a significant security risk. If any device is compromised, jailbroken, or reverse-engineered, the attacker obtains a credential that grants full org-level access. This key cannot be revoked without breaking every other device using it, and there is no way to determine which device made a particular API call.

Specific risks of embedded API keys:

  • No per-device revocation: Revoking the key cuts off every device in the org simultaneously.
  • No attribution: API calls made with the same key are indistinguishable. You cannot tell which device submitted a training update or identify a compromised device.
  • Extraction is trivial: On Android, APK decompilation reveals hardcoded strings in minutes. On iOS, runtime inspection tools can dump memory. Obfuscation does not provide real security.
  • Compliance failures: SOC 2, HIPAA, and PCI-DSS auditors flag long-lived credentials embedded in client applications as a finding.

The device token model eliminates all of these issues. Each device gets its own short-lived token, issued by your backend, with full audit trail and individual revocation capability.

Before

  • Client app embeds long-lived org API key
  • Key leakage risk and difficult revocation semantics

After

  • Backend keeps org API key secret
  • Client receives short-lived device tokens via bootstrap exchange

Prerequisites

Before starting the migration, verify:

  • Your backend service can securely store the org API key (secret manager, not source code)
  • You have a way to deliver bootstrap tokens to devices (app provisioning flow, push notification, or MDM)
  • The Octomil device auth endpoints are enabled for your org (check Dashboard -> Settings -> Device Auth)
  • Your SDK version supports device auth: Python SDK >= 0.5.0, iOS SDK >= 0.4.0, Android SDK >= 0.4.0
  • You have monitoring in place to track auth failures (see Monitoring Dashboard)
  • You have identified all client applications and app versions that currently embed the API key

Migration Steps

1. Keep existing org API key only in backend service

Move the API key from your client application code to your backend environment. The key should be stored in your deployment secret manager (AWS Secrets Manager, Vault, Railway secrets, etc.) and injected as an environment variable.

Before (insecure): The org API key is hardcoded in the client app and ships in the binary.

After (secure): The API key lives in your backend's secret manager (os.environ["OCTOMIL_API_KEY"]). Client apps never see it — they receive short-lived device tokens instead.

2. Add backend endpoint that returns bootstrap bearer token to trusted app session

Create an endpoint in your backend that your client app calls (after authenticating the user) to obtain a bootstrap token. Your backend uses the org API key to request the bootstrap token from Octomil.

# backend/routes/device_auth.py
import httpx
from fastapi import APIRouter, Depends
from your_app.auth import get_current_user

router = APIRouter()

@router.post("/device/bootstrap")
async def get_bootstrap_token(
device_id: str,
user = Depends(get_current_user), # Your app's user auth
):
"""
Authenticated endpoint that returns a bootstrap token for the device.
The org API key never leaves the backend.
"""
async with httpx.AsyncClient() as client:
response = await client.post(
"https://api.octomil.com/api/v1/device-auth/token",
headers={
"X-API-Key": os.environ["OCTOMIL_API_KEY"],
},
json={
"device_id": device_id,
"ttl": 900, # 15 minutes
},
)
response.raise_for_status()
return {"bootstrap_token": response.json()["bootstrap_token"]}

3. Integrate SDK device auth manager (bootstrap, refresh, revoke)

Update your client application to use the SDK's device auth flow instead of passing the API key directly.

Python SDK:

from octomil import DeviceClient

# Get bootstrap token from YOUR backend, then initialize
bootstrap_token = requests.post(
"https://your-backend.com/device/bootstrap",
json={"device_id": device_id},
headers={"Authorization": f"Bearer {user_session_token}"},
).json()["bootstrap_token"]

client = DeviceClient(bootstrap_token=bootstrap_token)
# SDK handles token refresh automatically from here
result = client.submit_training_update(weights=updated_weights)

iOS SDK (Swift):

let deviceClient = try await Octomil.DeviceClient(
bootstrapToken: bootstrapToken,
deviceId: UIDevice.current.identifierForVendor?.uuidString ?? ""
)
try await deviceClient.submitTrainingUpdate(weights: updatedWeights)

Android SDK (Kotlin):

val deviceClient = Octomil.DeviceClient(
context = applicationContext,
bootstrapToken = bootstrapToken,
deviceId = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
)
deviceClient.submitTrainingUpdate(weights = updatedWeights)

4. Remove org API key from all client bundles

Search your codebase for any remaining references to the API key in client-side code:

# Find hardcoded API keys in your codebase
grep -r "sk_live_\|sk_test_\|OCTOMIL_API_KEY" \
--include="*.swift" --include="*.kt" --include="*.py" --include="*.ts" \
--exclude-dir="backend" --exclude-dir="server" .

Remove every occurrence. If any are found in build artifacts (APK, IPA), the key must be rotated after migration is complete.

5. Roll out gradually by app version and monitor auth failures

Do not migrate all devices simultaneously. Use a phased approach.

Phased Rollout Strategy

PhaseDurationScopeGate Criteria
1. Internal testing1 week5-10 internal devices (iOS, Android, Python)Zero auth failures; bootstrap, refresh, and revocation validated
2. Canary1-2 weeks5% of production devices (feature flag)< 0.5% failure rate on new flow; pause if > 1%
3. Broad rollout2-4 weeks25% -> 50% -> 100%, hold 48h at each stageError rates stable at each stage; legacy flow still active as fallback
4. Deprecation2 weeks after 100%Announce cutoff, then disable legacy key pathAll devices migrated; cutoff date communicated

Monitoring Migration Progress

Track the migration using the following metrics and dashboard views:

Key Metrics

MetricExpected Trend
Device token adoption rateRising to 1.0
Legacy API key usageFalling to zero
Device token auth successesRising
Auth failure rate by methodComparable or improving

In the Monitoring Dashboard, create panels for migration progress (daily adoption %), failure rate comparison by auth method, and app version breakdown showing which versions still use the legacy flow.

Rollback

  • Temporarily permit old flow for a limited window
  • Keep strict telemetry on legacy calls
  • Set cutoff date and disable legacy key path

Detailed Rollback Procedure

If the device token flow causes unacceptable error rates during rollout:

  1. Immediate: Re-enable the legacy API key flow for affected devices. This requires no client update if the app has fallback logic:
# Client-side fallback (build this in during migration)
try:
client = DeviceClient(bootstrap_token=get_bootstrap_token())
except BootstrapError:
# Fallback to legacy flow (temporary)
client = LegacyClient(api_key=get_legacy_key())
report_fallback_event()
  1. Within 24 hours: Identify the root cause. Common issues:

    • Backend bootstrap endpoint returning errors (check backend logs)
    • Network timeout during bootstrap exchange (increase TTL or retry count)
    • SDK version incompatibility (verify minimum SDK versions)
  2. Fix and re-deploy: Address the root cause, test in staging, and resume the phased rollout from the last successful phase.

Success Criteria

  • 0 client bundles containing org API keys
  • 99% of devices using short-lived token flow

  • Revocation path validated in incident drills

Validation Checklist

After migration is complete, verify:

  • grep for API key patterns in all client repositories returns zero results
  • The legacy API key has been rotated (old key is no longer valid)
  • The octomil_api_key_auth_total{source="client"} metric is at zero for 7 consecutive days
  • A test revocation of a device token successfully blocks the device from API access
  • A test deprovisioning via SCIM successfully revokes all associated device tokens
  • The incident runbook includes device token revocation steps

Post-Migration Cleanup

After the migration is validated and the cutoff date has passed:

  1. Rotate the org API key. The old key may have been exposed in client bundles. Generate a new key in Dashboard -> Settings -> API Keys and update your backend service.
  2. Remove fallback code from client applications. The legacy client initialization path is dead code after migration.
  3. Update documentation and onboarding guides to reference the device token flow exclusively.
  4. Archive migration monitoring dashboards or repurpose them for ongoing device auth health monitoring.