{
  "slug": "hide-anthropic-api-key-expo",
  "title": "Hide Anthropic API Key in an Expo App",
  "metaDescription": "Keep your Anthropic key out of Expo builds and OTA updates. RealComposer injects x-api-key at the edge so EXPO_PUBLIC_ variables never carry a secret.",
  "headline": "Claude chat in Expo without secrets in EXPO_PUBLIC_",
  "category": "security",
  "categoryLabel": "Security & Secret Vault",
  "urgency": 10,
  "clientPlatform": "Expo",
  "upstreamServices": [
    "Anthropic"
  ],
  "searchIntentQuery": "hide anthropic api key in expo app",
  "directAnswerSummary": "EXPO_PUBLIC_ variables and app config extra fields are inlined into every Expo build and EAS Update bundle, so an Anthropic key placed there is public. Call a RealComposer pipeline instead: it injects ANTHROPIC_API_KEY as the x-api-key header at the edge and returns just the reply text.",
  "problem": {
    "title": "Why Expo apps leak Anthropic keys",
    "explanation": "Developers often move keys into EXPO_PUBLIC_ variables assuming environment variables are private. Expo inlines them into the JavaScript bundle, and EAS Update serves that bundle to every device, where it can be downloaded and searched.",
    "risks": [
      "Anthropic key inlined into the Hermes bundle",
      "OTA updates redistributing the key to every install",
      "Large Messages API payloads parsed on the JS thread"
    ]
  },
  "solutionSteps": [
    {
      "stepNumber": 1,
      "title": "Store credentials in Secret Vault",
      "description": "Save ANTHROPIC_API_KEY in RealComposer so the value never enters the Expo project."
    },
    {
      "stepNumber": 2,
      "title": "Configure the edge pipeline",
      "description": "Add the upstream steps with vault header injection, set allowed origins, and map only the fields the screen binds."
    },
    {
      "stepNumber": 3,
      "title": "Call the pipeline from Expo",
      "description": "Call your workspace edge URL with a restricted rc_live_ client token.",
      "codeSnippet": "const res = await fetch('https://realcomposer.com/v1/workspace/hide-anthropic-api-key-expo', {\n  method: 'POST',\n  headers: { Authorization: 'Bearer rc_live_client_token', 'Content-Type': 'application/json' },\n  body: JSON.stringify({ messages: [{ role: 'user', content: prompt }] }),\n});\nconst { reply } = await res.json();"
    }
  ],
  "pipelineConfig": {
    "name": "Hide Anthropic API Key in an Expo App",
    "method": "POST",
    "cacheTtlSeconds": 0,
    "authMode": "client_token",
    "steps": [
      {
        "stepKey": "anthropic",
        "upstreamUrlTemplate": "https://api.anthropic.com/v1/messages",
        "httpMethod": "POST",
        "headersTemplate": {
          "x-api-key": "{{secrets.ANTHROPIC_API_KEY}}",
          "anthropic-version": "2023-06-01",
          "Content-Type": "application/json"
        },
        "timeoutMs": 15000
      }
    ],
    "outputMapping": {
      "version": 1,
      "fields": [
        {
          "targetPath": "reply",
          "sourceStep": "anthropic",
          "sourcePath": "content.0.text"
        }
      ]
    }
  },
  "sampleBloatedInput": {
    "id": "msg_01Xf",
    "type": "message",
    "role": "assistant",
    "model": "claude-sonnet-4-5",
    "stop_reason": "end_turn",
    "content": [
      {
        "type": "text",
        "text": "Your itinerary is ready."
      }
    ],
    "usage": {
      "input_tokens": 180,
      "output_tokens": 32
    }
  },
  "sampleSlimmedOutput": {
    "reply": "Your itinerary is ready."
  },
  "curlSnippet": "curl -X POST \"https://realcomposer.com/v1/workspace/hide-anthropic-api-key-expo\" \\\n  -H \"Authorization: Bearer rc_live_client_token\"",
  "faqs": [
    {
      "question": "Can I store the Anthropic key as an EAS secret?",
      "answer": "Only for build steps. If app code reads it at runtime, it is bundled into the app and becomes public."
    },
    {
      "question": "Does this work in Expo Go and dev clients?",
      "answer": "Yes. The app only makes a standard fetch to the edge URL, so it behaves the same in Expo Go, development builds, and production."
    }
  ],
  "relatedRecipeSlugs": [
    "anthropic-claude-api-frontend-proxy",
    "stripe-proxy-react-native",
    "protect-supabase-service-role-key-expo"
  ],
  "links": {
    "page": "https://realcomposer.com/recipes/hide-anthropic-api-key-expo",
    "markdown": "https://realcomposer.com/recipes/hide-anthropic-api-key-expo.md",
    "json": "https://realcomposer.com/recipes/hide-anthropic-api-key-expo.json",
    "install": "https://realcomposer.com/dashboard/pipelines/new?recipe=hide-anthropic-api-key-expo&via=agent"
  }
}