Glad you're here.
" } }) { messageId success } } ``` ### CC, BCC, and attachments `to`, `cc`, and `bcc` accept arrays of recipients. Attachments are passed as base64-encoded content: ```graphql theme={null} mutation { sendgrid_sendEmail(email: { from: { email: "hello@yourapp.com" } to: [{ email: "ada@example.com" }] cc: [{ email: "team@yourapp.com" }] subject: "Receipt" content: [{ type: "text/html", value: "Receipt attached.
" }] attachments: [{ filename: "receipt.pdf" type: "application/pdf" content: "JVBERi0..." disposition: "attachment" }] }) { messageId success } } ``` ### Scheduled email Pass `sendAt` with an ISO 8601 timestamp to defer delivery: ```graphql theme={null} mutation { sendgrid_sendEmail(email: { from: { email: "hello@yourapp.com" } to: [{ email: "ada@example.com" }] subject: "Reminder: invoice due" content: [{ type: "text/html", value: "Heads up.
" }] sendAt: "2026-06-01T10:00:00Z" }) { messageId success } } ``` ### Dynamic templates For richer designs, use a SendGrid Dynamic Template (the template ID starts with `d-`): ```graphql theme={null} mutation { sendgrid_sendTemplate(email: { from: { email: "hello@yourapp.com" } to: [{ email: "ada@example.com" }] templateId: "d-1234567890abcdef" substitutions: { name: "Ada" orderNumber: "12345" totalAmount: "$99.99" } }) { messageId success } } ``` ### Bulk sends `sendgrid_sendBulkEmail` accepts an array of email payloads in a single call. Useful for onboarding sequences and one-off campaigns under SendGrid's limits. ## Contacts Add, update, and delete recipients in your SendGrid contact lists: ```graphql theme={null} mutation { sendgrid_addContact(contact: { email: "ada@example.com" firstName: "Ada" lastName: "Lovelace" customFields: { plan: "founder" } listIds: ["a1b2c3..."] }) } ``` ## Analytics Pull aggregate delivery metrics for a date range: ```graphql theme={null} query { sendgrid_getEmailStats(startDate: "2026-04-01", endDate: "2026-04-30") { delivered opens clicks bounces spamReports } } ``` `sendgrid_validateEmail` checks an address's deliverability score before you send. ## Webhooks In SendGrid, go to **Settings → Mail Settings → Event Webhook** and point it at the Archie-generated webhook URL for your project. Configure the webhook signing key so Archie can verify events. Supported events include `processed`, `delivered`, `opened`, `clicked`, `bounce`, `dropped`, `spamreport`, and `unsubscribe`. See [Webhooks](/docs/features/backend/integrations/webhooks). ## FAQ > **What sender domains can I use?** > > Any domain you've authenticated in SendGrid. Domain authentication (SPF, DKIM) is required for reliable deliverability — single-sender verification works for testing but limits volume. > **Why is my email going to spam?** > > Almost always a sender authentication issue. Make sure you've completed domain authentication in SendGrid, set up DMARC, and that your `from` address matches the authenticated domain. Warm new domains by sending gradually-increasing volume. > **Can I send marketing emails through this integration?** > > Yes, including dynamic templates and contact list segmentation. For high-volume marketing campaigns specifically, SendGrid's Marketing Campaigns UI gives you scheduling and analytics that the API doesn't expose. > **My API key returned 403 on email validation. What happened?** > > SendGrid's email validation endpoint requires a paid Email Validation add-on. If your key doesn't have it, `sendgrid_validateEmail` falls back to a basic regex check and returns a slightly lower score with a note explaining why. > **How do I track which user clicked a link?** > > Pass a `customArgs` object on the send. SendGrid attaches it to every event for that message — Archie surfaces those custom args in the webhook events you receive. # Shopify Source: https://archie.com/docs/backend/integrations/shopify Read and write Shopify store data — products, orders, customers, and inventory — through Archie's GraphQL API. The Shopify integration connects your Archie app to a Shopify store. Once configured, you can read and update products, orders, customers, and inventory through namespaced GraphQL operations and react to store events via webhooks. > [!NOTE] > > A typed TypeScript SDK for integrations is coming with the next archie-app release. This page documents the GraphQL operation surface available today. ## Enable the integration Open **Integrations** in the left sidebar and pick Shopify. You'll need a Shopify Partner app or a custom app installed on your store (Shopify Admin → **Apps and sales channels → Develop apps**). From the app's settings: * **API Key** — under **API credentials**. * **API Secret** — same place. Used to authenticate API calls and verify webhook signatures. * **Store URL** — your shop's `.myshopify.com` domain (e.g. `acme.myshopify.com`). * **Environment** — `Development` or `Production`, so credentials route to the right environment. Optional: * **Access Token** — set this if you want to skip the OAuth handshake and use a direct admin token from a private app. * **Webhook Secret** — separate from the API secret; used specifically to verify Shopify webhook payloads. Secrets are encrypted with AES-256-GCM at rest. ## What you can do The integration covers the most common Shopify Admin API surfaces: * **Products** — list, get, create, update, delete; manage variants and metafields * **Orders** — list, get, create, update, fulfill, refund, cancel * **Customers** — list, get, create, update, search * **Inventory** — read and adjust stock levels per location * **Webhooks** — subscribe to store events from your Archie app ## Reading and writing data ### List products ```graphql theme={null} query { shopify_products(first: 25) { edges { node { id title status totalInventory priceRange { minVariantPrice { amount currency } maxVariantPrice { amount currency } } } } pageInfo { hasNextPage endCursor } } } ``` ### Create an order draft ```graphql theme={null} mutation { shopify_createDraftOrder(input: { customerId: "gid://shopify/Customer/12345" lineItems: [ { variantId: "gid://shopify/ProductVariant/67890", quantity: 2 } ] note: "Manual order from internal CRM" }) { id invoiceUrl } } ``` ### Update inventory ```graphql theme={null} mutation { shopify_adjustInventory(input: { inventoryItemId: "gid://shopify/InventoryItem/...." locationId: "gid://shopify/Location/...." delta: -1 }) { available } } ``` ### Search customers ```graphql theme={null} query { shopify_searchCustomers(query: "email:ada@example.com") { edges { node { id firstName lastName email ordersCount totalSpent } } } } ``` ## Webhooks In Shopify Admin, go to **Settings → Notifications → Webhooks** and add the events you want, pointing each at the Archie-generated Shopify webhook URL for your project. Archie verifies the HMAC signature using your webhook secret before storing or dispatching the event. Common events to subscribe to: * `orders/create`, `orders/paid`, `orders/cancelled`, `orders/fulfilled` * `products/create`, `products/update`, `products/delete` * `customers/create`, `customers/update` * `inventory_levels/update` * `app/uninstalled` (so you can clean up if your app is removed) See [Webhooks](/docs/features/backend/integrations/webhooks) for receiving events in custom functions. ## FAQ > **Custom app vs. Partner app — which should I use?** > > For a single store, a custom app inside Shopify Admin is simpler. For multi-store distribution or a public app on the Shopify App Store, you need a Partner app with OAuth. Both work with this integration; the credentials are the same shape. > **Why are IDs in the format `gid://shopify/...`?** > > Shopify's GraphQL Admin API uses Global IDs. The legacy REST IDs (numeric) and GraphQL IDs are interchangeable — Archie accepts either format, but the GraphQL form is what comes back in responses. > **How do I sync product changes from Shopify into my Archie data model?** > > Subscribe to `products/update` and `products/create` webhooks. In the handler, upsert into your Archie data model. For initial sync, paginate `shopify_products` until `hasNextPage` is false. > **What about rate limits?** > > Shopify rate-limits the Admin API on a leaky-bucket model — roughly 2 requests per second on standard plans, more on Shopify Plus. If you need to do bulk reads, use Shopify's Bulk Operation API rather than paginating manually; the integration exposes `shopify_bulkOperationRunQuery` for it. > **Can I run the integration against a development store?** > > Yes. Development stores work the same as live stores. Use the development store's `.myshopify.com` URL and a custom app installed there, with your integration environment set to `Development`. # Slack Source: https://archie.com/docs/backend/integrations/slack Send notifications and interactive messages to Slack channels and DMs from your Archie app. The Slack integration lets your Archie app post messages, alerts, and interactive Block Kit cards into your team's Slack workspace. Once connected, you call Slack through namespaced GraphQL operations. > [!NOTE] > > A typed TypeScript SDK for integrations is coming with the next archie-app release. This page documents the GraphQL operation surface available today. ## Enable the integration Open **Integrations** in the left sidebar and pick Slack. You'll need a [Slack App](https://api.slack.com/apps) with the right scopes installed in your workspace. From the app's settings: * **Bot Token** — `xoxb-...`. Found under **OAuth & Permissions**. Needs `chat:write` for posting; add `chat:write.public` if you want to post to channels the bot isn't a member of. * **App Token** — `xapp-...`. Found under **Basic Information → App-Level Tokens**. Needed if you use Socket Mode or subscribe to events. * **Signing Secret** — under **Basic Information → App Credentials**. Used to verify requests Slack sends to your app. * **Environment** — pick which environment this configuration applies to (e.g. `Production`, `Staging`). Tokens are encrypted at rest and only decrypted at request time. ## What you can do * **Send messages** — to channels, threads, or DMs * **Send rich messages** — Block Kit blocks, attachments, buttons * **Schedule messages** — deliver later at a chosen time * **Update and delete** — edit or remove a previously-sent message * **Receive events** — slash commands, button clicks, and interactivity callbacks via webhooks ## Sending a message ### A simple notification ```graphql theme={null} mutation { slack_sendMessage(input: { channel: "#general" text: "Build #482 deployed to production" }) { ts channel } } ``` The returned `ts` is the message timestamp — keep it if you want to update or thread on it later. ### Block Kit For richer messages with buttons or sections, pass a Block Kit `blocks` array: ```graphql theme={null} mutation { slack_sendMessage(input: { channel: "C0123456789" text: "New signup" blocks: """ [ { "type": "section", "text": { "type": "mrkdwn", "text": "*New signup:* ada@example.com" }}, { "type": "actions", "elements": [ { "type": "button", "text": { "type": "plain_text", "text": "View" }, "url": "https://yourapp.com/admin/users/123" } ]} ] """ }) { ts } } ``` ### Reply in a thread Pass `threadTs` to thread under an existing message: ```graphql theme={null} mutation { slack_sendMessage(input: { channel: "C0123456789" threadTs: "1714060800.000100" text: "Resolution: rolled back release v1.2.3" }) { ts } } ``` ### Direct messages Pass a user ID (`U...`) as the channel to DM that user. The bot must have the `chat:write` scope and the user must be in a workspace where the app is installed. ### Scheduled messages ```graphql theme={null} mutation { slack_scheduleMessage(input: { channel: "#announcements" text: "Office reopens in 1 hour" postAt: "2026-06-01T14:00:00Z" }) { scheduledMessageId } } ``` ## Webhooks If you want to receive events from Slack — slash commands, button clicks, mention events — point your Slack App's **Event Subscriptions** request URL and **Interactivity** request URL at the Archie-generated Slack webhook URL for your project. Archie verifies the signing secret on every event. See [Webhooks](/docs/features/backend/integrations/webhooks) for handling them in custom functions. ## FAQ > **Channel name vs. channel ID — which should I pass?** > > Both work for public channels. Channel IDs (`C0123456789`) are more reliable because they don't change if the channel is renamed. For private channels and DMs, the ID is required and the bot must be a member. > **My bot can't post to a channel. What's wrong?** > > The bot has to be invited to the channel — `/invite @yourbot` from inside Slack. Public channels can be posted to without joining if you've granted the `chat:write.public` scope, but private channels always require membership. > **How do I respond to a button click?** > > Slack POSTs an interactivity payload to the URL configured under **Interactivity & Shortcuts**. Point that at Archie's webhook URL and handle the action in a custom function. Reply within 3 seconds with a 200 OK to acknowledge, then post a follow-up message asynchronously if needed. > **Can I send DMs to users who aren't in the workspace?** > > No. Slack only allows messaging users who are members of a workspace your app is installed in. For broader notifications, use email (SendGrid) or SMS (Twilio). > **What's the rate limit?** > > Slack's Web API allows roughly 1 message per second per channel, with short bursts allowed. For high-volume notifications, batch into a single message with multiple Block Kit sections or use a thread to group related updates. # Stripe Source: https://archie.com/docs/backend/integrations/stripe Process payments, manage subscriptions, and run a Stripe-hosted billing portal — all through Archie's auto-generated GraphQL API. The Stripe integration handles payments, subscriptions, invoicing, and refunds in your Archie app. Once you connect it, Archie exposes a namespaced set of GraphQL queries and mutations (`stripe_*`) that your frontend, custom functions, and backend routes can call. > [!NOTE] > > A typed TypeScript SDK for integrations is coming with the next archie-app release. This page documents the GraphQL operation surface available today. ## Enable the integration Open the **Integrations** module in the left sidebar and pick Stripe from the catalog. You'll need from your [Stripe dashboard](https://dashboard.stripe.com/apikeys): * **Secret Key** — starts with `sk_test_` (test mode) or `sk_live_` (production). Used by the backend to authenticate API calls. * **Publishable Key** — starts with `pk_test_` or `pk_live_`. Safe to use in the frontend. * **Environment** — pick `TEST` while building, `LIVE` when you're ready to take real payments. * **Webhook Secret** *(optional)* — `whsec_...`. Required if you want Archie to verify Stripe webhook signatures. Archie encrypts the secret key with AES-256-GCM before storing it. Keys are scoped per project per environment, so test credentials on a development branch never touch production. ## What you can do The integration adds GraphQL operations for everything most apps need from Stripe: * **Customers** — `stripe_customer`, `stripe_customers`, `stripe_createCustomer`, `stripe_updateCustomer`, `stripe_deleteCustomer` * **Payment intents** — `stripe_paymentIntent`, `stripe_paymentIntents`, `stripe_createPaymentIntent`, `stripe_updatePaymentIntent`, `stripe_confirmPaymentIntent`, `stripe_cancelPaymentIntent` * **Subscriptions** — `stripe_subscription`, `stripe_subscriptions`, `stripe_createSubscription`, `stripe_updateSubscription`, `stripe_cancelSubscription` * **Products and prices** — `stripe_products`, `stripe_createProduct`, `stripe_prices`, `stripe_createPrice` * **Invoices** — `stripe_invoice`, `stripe_invoices`, `stripe_payInvoice` * **Refunds** — `stripe_refunds`, `stripe_createRefund` * **Checkout sessions** — `stripe_createCheckoutSession` for Stripe-hosted checkout * **Billing portal** — `stripe_createBillingPortalSession` for self-serve subscription management * **Payment methods** — `stripe_paymentMethods`, `stripe_attachPaymentMethod`, `stripe_detachPaymentMethod` * **Webhook events** — `stripe_webhookEvents` for inspecting signed events Archie has received All list queries support cursor-based pagination via `first` and `after`. ## Calling Stripe from your app ### Create a customer ```graphql theme={null} mutation { stripe_createCustomer(input: { name: "Ada Lovelace" email: "ada@example.com" phone: "+15551234567" metadata: { plan: "founder" } }) { id email createdAt } } ``` ### Create a Checkout session For Stripe-hosted checkout (the easiest path for most builders): ```graphql theme={null} mutation { stripe_createCheckoutSession(input: { mode: "subscription" customerEmail: "ada@example.com" successUrl: "https://yourapp.com/welcome" cancelUrl: "https://yourapp.com/pricing" lineItems: [{ priceId: "price_1ABC...", quantity: 1 }] }) { id url } } ``` Redirect the user to the returned `url`. Stripe handles the payment and redirects to your `successUrl` when complete. ### Open the billing portal Let customers manage their own subscription: ```graphql theme={null} mutation { stripe_createBillingPortalSession(input: { customerId: "cus_..." returnUrl: "https://yourapp.com/account" }) { url } } ``` ### Create a payment intent (manual flow) If you want to render a custom checkout with Stripe.js or Stripe Elements: ```graphql theme={null} mutation { stripe_createPaymentIntent(input: { amount: 49.99 currency: "usd" customerId: "cus_..." automaticPaymentMethods: true }) { id clientSecret status } } ``` Pass the returned `clientSecret` to your frontend Stripe.js confirm step. ## Webhooks When you save the integration, Archie generates a webhook URL specific to your project and environment. Add it in the Stripe dashboard under **Developers → Webhooks**, and provide the resulting signing secret in the integration config. Archie verifies every incoming event before storing it. Query received events with `stripe_webhookEvents`, or react to them inside a custom function — see [Webhooks](/docs/features/backend/integrations/webhooks). Common events you'll likely care about: * `payment_intent.succeeded` * `payment_intent.payment_failed` * `customer.subscription.created` / `updated` / `deleted` * `invoice.paid` / `invoice.payment_failed` * `checkout.session.completed` ## FAQ > **Test mode vs. live mode — when does each apply?** > > Archie selects credentials based on the environment your app is running in. Development environments use the keys saved with `TEST`; production uses the ones saved with `LIVE`. Setting up both up front means you can swap stages without touching code. > **Can I use Stripe.js or Stripe Elements on the frontend?** > > Yes. Use `stripe_createPaymentIntent` to get a `clientSecret`, then confirm it on the frontend with the publishable key. The publishable key is returned from the integration config and is safe to expose in client code. > **How do I refund a payment?** > > Call `stripe_createRefund` with the `paymentIntentId`. Omit `amount` for a full refund or pass an amount for partial. Refunds start as `pending` and update to `succeeded` or `failed` once Stripe processes them. > **What happens to webhook events if my app is down?** > > Stripe retries failed webhook deliveries with exponential backoff for up to three days. Once your app is reachable, Archie verifies and stores the event normally. You can also replay events from the Stripe dashboard. > **Can I use a specific Stripe SDK version directly?** > > Yes. Add the `stripe` package to your custom function and call it with `ctx.integrations.stripe.config.secretKey`. The GraphQL operations cover most cases; the SDK is for anything they don't expose. # Twilio Source: https://archie.com/docs/backend/integrations/twilio Send SMS, place voice calls, and run verification flows from your Archie app through Twilio's programmable communications API. The Twilio integration handles SMS, voice, and verification in your Archie app. Once connected, you can send messages, kick off verification codes, and receive inbound events — all through the auto-generated GraphQL API. > [!NOTE] > > A typed TypeScript SDK for integrations is coming with the next archie-app release. This page documents the GraphQL operation surface available today. ## Enable the integration Open **Integrations** in the left sidebar and pick Twilio. You'll need from your [Twilio Console](https://console.twilio.com/): * **Account SID** — starts with `AC...`. Acts as the username for API calls. * **Auth Token** — your account's secret. Treat it like a password. Optional, depending on what you're building: * **Messaging Service SID** — `MG...`, if you use a Messaging Service for SMS. * **Verify Service SID** — `VA...`, if you use Twilio Verify for OTP and 2FA flows. The auth token is encrypted with AES-256-GCM at rest and only decrypted in the backend at request time. ## What you can do * **SMS** — send single and bulk messages, with Messaging Service support * **Voice** — place calls, send TwiML responses, manage call status * **Verify** — start verification challenges, check codes, run 2FA flows * **Webhook events** — receive inbound SMS, status callbacks, and Verify events ## Sending an SMS ```graphql theme={null} mutation { twilio_sendSms(input: { to: "+15551234567" from: "+15557654321" body: "Your code is 123456" }) { sid status } } ``` For high-volume SMS, send through a Messaging Service instead of a single from-number — it handles rotation, carrier registration, and opt-out: ```graphql theme={null} mutation { twilio_sendSms(input: { to: "+15551234567" messagingServiceSid: "MG..." body: "Welcome to Yourapp" }) { sid status } } ``` ## Verification flows (Twilio Verify) Start a verification: ```graphql theme={null} mutation { twilio_startVerification(input: { serviceSid: "VA..." to: "+15551234567" channel: "sms" }) { sid status } } ``` Check a code: ```graphql theme={null} mutation { twilio_checkVerification(input: { serviceSid: "VA..." to: "+15551234567" code: "123456" }) { valid status } } ``` Verify supports SMS, voice, email, and TOTP channels — pick the one that matches your flow. ## Placing a voice call ```graphql theme={null} mutation { twilio_makeCall(input: { to: "+15551234567" from: "+15557654321" twimlUrl: "https://yourapp.com/voice/welcome" }) { sid status } } ``` `twimlUrl` should return TwiML that tells Twilio what to say or play. ## Webhooks Configure inbound webhooks in the Twilio Console: * **Phone Numbers → Active numbers → \[number] → Messaging** — point at Archie's generated SMS webhook URL for inbound messages. * **Phone Numbers → Active numbers → \[number] → Voice** — point at Archie's generated voice webhook URL. * **Verify Service → Webhooks** — point at Archie's Verify webhook URL for status changes. Archie verifies Twilio's `X-Twilio-Signature` header before accepting events. See [Webhooks](/docs/features/backend/integrations/webhooks) for handling them in custom functions. ## FAQ > **Do I need a Messaging Service or can I just use a single from-number?** > > A single from-number works fine for low volume and dev testing. Use a Messaging Service when you start sending more than a few hundred SMS per day, want number rotation across multiple numbers, or need carrier-mandated registration (A2P 10DLC in the US). > **What's the difference between sending an OTP via SMS directly and using Twilio Verify?** > > Verify handles code generation, expiry, attempt limits, and channel fallback (SMS, voice, email, TOTP) for you. If you send OTPs via raw SMS, you implement all of that yourself. Use Verify unless you have a reason not to. > **How do I receive inbound SMS replies?** > > Set the messaging webhook on your Twilio number to Archie's generated SMS webhook URL. Inbound messages arrive as webhook events you can react to in a custom function — see [Webhooks](/docs/features/backend/integrations/webhooks). > **Can I send international SMS?** > > Yes, but you need to enable geo permissions in the Twilio Console (**Messaging → Settings → Geo Permissions**) and may need country-specific sender registration. Twilio also charges per-country rates. > **What happens to my flow if Twilio is down?** > > Your call to `twilio_sendSms` returns an error and your code can decide what to do — retry, fall back to email through SendGrid, or queue for later. Webhook events are retried by Twilio with backoff if your endpoint isn't reachable. # Webhooks Source: https://archie.com/docs/backend/integrations/webhooks Receive webhooks from your app or send them to external systems. Webhooks allow you to receive real-time HTTP notifications when data changes in your Archie Core project. When a record is created, updated, or deleted, Archie Core sends a `POST` request to your configured URL with the event details. ## How webhooks work 1. **Register** a webhook subscription specifying the table, events, and target URL 2. **Data changes** — when a matching mutation occurs (via REST API or GraphQL), an event is published 3. **Delivery** — the webhook service sends an HTTP `POST` to your URL with the event payload 4. **Verification** — validate the HMAC signature to ensure the request is authentic ## Webhook management API All webhook management endpoints are under `/api/rest/_webhooks` and require a management API token. ### Required headers | Header | Required | Description | | - | - | - | | `Authorization` | Yes | `Bearer