Skip to content

Stripe GraphQL API

Query Stripe data through your GraphQL API using @nhost/stripe-graphql-js

Stripe GraphQL payments subscriptions invoices remote schema billing

The @nhost/stripe-graphql-js package lets you expose Stripe’s API as a GraphQL Remote Schema. Once connected, you can query Stripe customers, subscriptions, invoices, payment methods, and more alongside your existing data in a single GraphQL request.

sequenceDiagram
actor C as Client
participant G as GraphQL Engine
participant F as Nhost Function<br/>(stripe-graphql-js)
participant S as Stripe API
C->>G: GraphQL query { stripe { customer { ... } } }
G->>F: Forward remote schema query
F->>F: Verify JWT / admin secret
F->>F: Run isAllowed() check
F->>S: Stripe API request
S-->>F: Stripe data
F-->>G: GraphQL response
G-->>C: Unified response

Your client sends a single GraphQL query to the GraphQL engine. The engine identifies the stripe field as a Remote Schema and forwards it to the Nhost Function running @nhost/stripe-graphql-js. The function authenticates the request, checks permissions, fetches data from Stripe, and returns it through the GraphQL engine back to the client.

  1. Install the package

    In your Nhost project, install the dependency:

    Terminal window
    pnpm add @nhost/stripe-graphql-js
  2. Create the serverless function

    Create a file at functions/graphql/stripe.ts:

    import { createStripeGraphQLServer } from '@nhost/stripe-graphql-js';
    const server = createStripeGraphQLServer();
    export default server;
  3. Add the Stripe secret key

    First, store your Stripe secret key as a project secret. In the Nhost dashboard go to Settings > Secrets, or use the CLI:

    Terminal window
    nhost secrets create STRIPE_SECRET_KEY sk_live_...

    Then expose it as an environment variable in nhost/nhost.toml:

    [[global.environment]]
    name = 'STRIPE_SECRET_KEY'
    value = '{{ secrets.STRIPE_SECRET_KEY }}'
  4. Register as a Remote Schema

    Add the function as a Remote Schema in nhost/metadata/remote_schemas.yaml:

    - name: stripe
    definition:
    url: '{{NHOST_FUNCTIONS_URL}}/graphql/stripe'
    timeout_seconds: 60
    customization: {}

    Or add it through the dashboard under GraphQL > Remote Schemas, using {{NHOST_FUNCTIONS_URL}}/graphql/stripe as the URL.

All queries are namespaced under the stripe field:

QueryArgumentsDescription
stripe.customerid (required)Get a single customer by ID
stripe.customersemail, limit, startingAfter, endingBeforeList customers with optional filtering and pagination

A customer object includes nested fields that resolve additional Stripe data:

Nested FieldDescription
subscriptionsCustomer’s active subscriptions
invoicesCustomer’s invoices
paymentMethodsCustomer’s payment methods (accepts type, limit, startingAfter, endingBefore)
paymentIntentsCustomer’s payment intents
chargesCustomer’s charges

Additional root queries (admin only):

QueryArgumentsDescription
stripe.connectedAccountid (required)Get a connected account
stripe.connectedAccountsList all connected accounts
MutationArgumentsDescription
stripe.createBillingPortalSessioncustomer (required), returnUrl, configuration, localeCreate a Stripe Billing Portal session

Fetch a customer with subscriptions and payment methods

Section titled “Fetch a customer with subscriptions and payment methods”
query {
stripe {
customer(id: "cus_ABC123") {
id
name
email
subscriptions {
data {
id
status
items {
data {
price {
unitAmount
currency
product {
name
}
}
}
}
}
}
paymentMethods(type: card) {
data {
id
card {
brand
last4
expMonth
expYear
}
}
}
}
}
}
query {
stripe {
customer(id: "cus_ABC123") {
invoices {
data {
id
status
amountDue
amountPaid
currency
created
hostedInvoiceUrl
invoicePdf
}
}
}
}
}
mutation {
stripe {
createBillingPortalSession(
customer: "cus_ABC123"
returnUrl: "https://myapp.com/account"
) {
url
}
}
}

By default, only admin requests (those with a valid admin secret header) are allowed. You can provide a custom isAllowed function to implement fine-grained access control:

import {
createNhostClient,
withAdminSession,
} from '@nhost/nhost-js';
import { Context, createStripeGraphQLServer } from '@nhost/stripe-graphql-js';
const nhost = createNhostClient({
subdomain: process.env['NHOST_SUBDOMAIN']!,
region: process.env['NHOST_REGION']!,
configure: [
withAdminSession({
adminSecret: process.env['NHOST_ADMIN_SECRET']!,
}),
],
});
const server = createStripeGraphQLServer({
isAllowed: async (stripeCustomerId: string, context: Context) => {
const { isAdmin, userClaims } = context;
// Admins can access any customer
if (isAdmin) {
return true;
}
// Otherwise, verify the user owns this Stripe customer.
// For example, look up the mapping in your database:
const userId = userClaims?.['x-hasura-user-id'];
if (!userId) {
return false;
}
// Query your database to check if this user owns the Stripe customer
const resp = await nhost.graphql.request({
query: `
query ($userId: uuid!, $stripeCustomerId: String!) {
users(where: {
id: { _eq: $userId },
metadata: { _contains: { stripeCustomerId: $stripeCustomerId } }
}) {
id
}
}
`,
variables: { userId, stripeCustomerId },
});
return (resp.body.data?.users?.length ?? 0) > 0;
},
});
export default server;

The isAllowed function receives:

  • stripeCustomerId: The Stripe customer ID being accessed
  • context: An object containing:
    • isAdmin — Whether the request has admin privileges
    • userClaims — The decoded JWT claims (includes x-hasura-user-id, x-hasura-default-role, x-hasura-allowed-roles).

The function is called for customer-scoped queries and mutations. Admin-only queries like connectedAccounts check isAdmin directly.

The createStripeGraphQLServer function accepts these options:

OptionTypeDefaultDescription
isAllowed(stripeCustomerId, context) => boolean | Promise<boolean>Admin-onlyCustom authorization function
corsCORSOptionsCORS configuration
graphiqlbooleanfalseEnable the GraphiQL interface
maskedErrorsbooleantrueMask error details in responses
VariableRequiredDescription
STRIPE_SECRET_KEYYesYour Stripe API secret key
NHOST_JWT_SECRETAutoSet automatically by Nhost. Used to verify user JWTs
NHOST_ADMIN_SECRETAutoSet automatically by Nhost. Used to verify admin requests
NHOST_WEBHOOK_SECRETAutoSet automatically by Nhost. Used to verify internal requests from the GraphQL engine