{
  "slug": "call-stripe-from-tooljet-securely",
  "title": "Call Stripe API from ToolJet Securely",
  "metaDescription": "Call Stripe from ToolJet apps without a secret key in RunJS. RealComposer injects STRIPE_SECRET_KEY at the edge and returns only the fields you bind.",
  "headline": "Stripe lookups for ToolJet support tools without RunJS secrets",
  "category": "security",
  "categoryLabel": "Security & Secret Vault",
  "urgency": 9,
  "clientPlatform": "ToolJet",
  "upstreamServices": [
    "Stripe"
  ],
  "searchIntentQuery": "call stripe api from tooljet securely",
  "directAnswerSummary": "Do not call Stripe from a ToolJet RunJS query, because RunJS executes in the browser and exposes the secret key. Add a RealComposer pipeline as a REST API data source instead. The edge injects STRIPE_SECRET_KEY from the vault and returns a compact customer and subscription object for your tables.",
  "problem": {
    "title": "Why ToolJet RunJS queries leak Stripe keys",
    "explanation": "Support teams often build Stripe lookup panels in ToolJet with a quick RunJS fetch. That code runs in each agent browser, so the sk_live_ key shows up in DevTools and can be copied by anyone with app access, including public app links.",
    "risks": [
      "sk_live_ key visible in RunJS source and network requests",
      "Public ToolJet apps letting anyone trigger refunds or lookups",
      "Expanded Stripe objects slowing ToolJet tables with unused fields"
    ]
  },
  "solutionSteps": [
    {
      "stepNumber": 1,
      "title": "Store credentials in Secret Vault",
      "description": "Save STRIPE_SECRET_KEY in RealComposer so the value never enters the ToolJet 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": "Add the pipeline as a ToolJet REST API data source",
      "description": "Call your workspace edge URL with a restricted rc_live_ client token.",
      "codeSnippet": "// ToolJet REST API data source\nBase URL: https://realcomposer.com/v1/workspace/call-stripe-from-tooljet-securely\nHeaders:  Authorization: Bearer rc_live_client_token\nQuery:    customerId = {{components.table1.selectedRow.stripe_id}}"
    }
  ],
  "pipelineConfig": {
    "name": "Call Stripe API from ToolJet Securely",
    "method": "GET",
    "cacheTtlSeconds": 0,
    "authMode": "client_token",
    "steps": [
      {
        "stepKey": "stripe",
        "upstreamUrlTemplate": "https://api.stripe.com/v1/customers/{{query.customerId}}?expand[]=subscriptions",
        "httpMethod": "GET",
        "headersTemplate": {
          "Authorization": "Bearer {{secrets.STRIPE_SECRET_KEY}}"
        },
        "timeoutMs": 3000
      }
    ],
    "outputMapping": {
      "version": 1,
      "fields": [
        {
          "targetPath": "customerId",
          "sourceStep": "stripe",
          "sourcePath": "id"
        },
        {
          "targetPath": "name",
          "sourceStep": "stripe",
          "sourcePath": "name"
        },
        {
          "targetPath": "plan",
          "sourceStep": "stripe",
          "sourcePath": "subscriptions.data.0.items.data.0.price.nickname"
        },
        {
          "targetPath": "status",
          "sourceStep": "stripe",
          "sourcePath": "subscriptions.data.0.status"
        }
      ]
    }
  },
  "sampleBloatedInput": {
    "id": "cus_Q2x8Lm",
    "object": "customer",
    "email": "ada@example.com",
    "name": "Ada Lovelace",
    "invoice_settings": {
      "default_payment_method": "pm_1Pz",
      "footer": null
    },
    "metadata": {
      "crm_id": "8812"
    },
    "subscriptions": {
      "object": "list",
      "data": [
        {
          "id": "sub_1Px",
          "status": "active",
          "current_period_end": 1767225600,
          "items": {
            "object": "list",
            "data": [
              {
                "price": {
                  "nickname": "Pro"
                }
              }
            ]
          }
        }
      ]
    }
  },
  "sampleSlimmedOutput": {
    "customerId": "cus_Q2x8Lm",
    "name": "Ada Lovelace",
    "plan": "Pro",
    "status": "active"
  },
  "curlSnippet": "curl -X GET \"https://realcomposer.com/v1/workspace/call-stripe-from-tooljet-securely\" \\\n  -H \"Authorization: Bearer rc_live_client_token\"",
  "faqs": [
    {
      "question": "Why not store the Stripe key on a ToolJet data source?",
      "answer": "That works for internal apps, but every app that needs Stripe repeats the setup. A RealComposer pipeline centralizes the key, slims the response, and can be shared across ToolJet, Retool, and mobile clients."
    },
    {
      "question": "Can I use a restricted Stripe key?",
      "answer": "Yes. Store an rk_live_ restricted key with read access to customers and subscriptions in the vault so the pipeline cannot issue refunds."
    }
  ],
  "relatedRecipeSlugs": [
    "connect-stripe-to-retool-securely",
    "appsmith-secure-api-proxy",
    "fix-cors-error-tooljet"
  ],
  "links": {
    "page": "https://realcomposer.com/recipes/call-stripe-from-tooljet-securely",
    "markdown": "https://realcomposer.com/recipes/call-stripe-from-tooljet-securely.md",
    "json": "https://realcomposer.com/recipes/call-stripe-from-tooljet-securely.json",
    "install": "https://realcomposer.com/dashboard/pipelines/new?recipe=call-stripe-from-tooljet-securely&via=agent"
  }
}