Snapshot

Selections

  • Deployment: Embedded
  • Binding: Attach to existing server
  • Database: PostgreSQL
  • Queues: Redis
  • Webhooks: Webhooks enabled
  • Providers: Google (Gmail)
  • Advanced: OpenTelemetry

Pre-rendered from the setup wizard so search engines can crawl every combination without JavaScript.

Riposte Setup Guide: Embedded (Attach) • PostgreSQL • Redis • Webhooks enabled • Google (Gmail)

Pre-generated Riposte setup wizard guide for embedded deployment with PostgreSQL storage. Redis queues enabled. webhooks configured. provider coverage: google (gmail). advanced: opentelemetry. Includes installation, configuration, integration code, and operational callouts..

📋 Setup Overview

Pre-generated Riposte setup instructions for a embedded deployment backed by postgresql with redis and webhooks enabled.

What you'll build

Embed Riposte directly into your existing Node.js or TypeScript service so the messaging engine runs beside the rest of your stack with minimal latency.

PostgreSQL gives you durable, production-grade storage, ready for high-volume inbox synchronization and queueing.

Authenticate Gmail inboxes with Google OAuth and reuse the same consent screen flow from the wizard in production.

Key ingredients

  • Deployment Embedded
  • Database PostgreSQL
  • Queues Redis
  • Webhooks Webhooks enabled
  • Providers Google (Gmail)
  • Advanced OpenTelemetry tracing and metrics

Redis is provisioned for background work queues and fan-out so long running sync jobs do not block user traffic.

Webhooks are enabled so downstream systems can respond to events such as message.received—remember to store and rotate your signing secret.

Advanced features enabled: OpenTelemetry tracing and metrics. Wire those signals into your observability stack before going live.

Embedded App

🚀 Installation & Bootstrap

Install the Riposte server inside your app and boot it alongside your existing framework.

src/server.ts
import Fastify from 'fastify'
import { createRiposteServer } from '@riposte.co/server'

// Note: This example uses Fastify, but embedded mode also works with Express and Koa
const app = Fastify()

async function start() {
  const riposte = await createRiposteServer({
    hostServer: app,
    initializeWorkspace: true,

    config: {
      database: {
        url: process.env.DATABASE_URL!,
      },
      redisUrl: process.env.REDIS_URL ?? 'redis://localhost:6379',
      providers: {
        google: {
          clientId: process.env.GOOGLE_CLIENT_ID!,
          clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
          redirectUri: process.env.GOOGLE_REDIRECT_URI ?? 'http://localhost:4000/riposte/providers/gmail/callback',
        },
      },
      webhooks: {
        default: {
          isActive: true,
          url: process.env.RIPOSTE_WEBHOOK_URL ?? 'https://example.com/webhooks/riposte',
          eventTypes: ["message.received","message.sent"],
        },
      },
      logging: {
        openTelemetry: {
          enabled: true,
          url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT!,
          serviceName: process.env.OTEL_SERVICE_NAME ?? "riposte-server",
        },
      },
    },
  })

  await riposte.start()
  await app.listen({ port: 4000 })
  console.log('Riposte ready at http://localhost:4000/riposte')
}

start()
Environment first: Keep secrets in .env (or your secrets manager) and reference them from the runtime config you pass to createRiposteServer.
Admin portal: Once the server is running, open http://localhost:4000/riposte. Passing adminPortal: true boots the portal with default admin/admin credentials—change them in the UI or via environment variables.

⚙️ Configuration

Drop these variables into .env (or your secrets manager) before booting the server.

Environment coverage

  • 🔑 API key for SDK & REST authentication
  • 🗄️ PostgreSQL database connection
  • ⚡ Redis-backed queues and cron
  • 🔗 Webhooks (message.received, message.sent)
  • 📧 Google OAuth client credentials
  • 📊 OpenTelemetry exporter endpoint & service name
.env
RIPOSTE_API_KEY=come-up-with-your-own-secure-api-key
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/riposte
REDIS_URL=redis://localhost:6379
RIPOSTE_WEBHOOK_URL=https://example.com/webhooks/riposte
GOOGLE_CLIENT_ID=your-google-oauth-client-id
GOOGLE_CLIENT_SECRET=your-google-oauth-client-secret
GOOGLE_REDIRECT_URI=http://localhost:4000/riposte/providers/gmail/callback
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
OTEL_SERVICE_NAME=riposte-integration
Apply changes: Restart Riposte after editing .env so the new credentials load into the runtime.

📮 Providers

Console steps and environment variables for each provider you enabled.

🔍 Google Setup

Capture OAuth client credentials and drop them into your environment:

  1. Open Google Cloud Console and create OAuth client credentials.
  2. Configure the consent screen for external users if you haven't already.
  3. Use the scope planner to copy the Gmail + People API scopes you need.
  4. Set GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REDIRECT_URI in .env, then restart Riposte.

Integration choices

  • Connection mode: OAuth consent screen
  • Accounts expected: 5
💡 Tip: Need instructions? Open the Google Workspace guide or Microsoft 365 guide for console setup and scope recommendations.

🔗 Integration Code

Add Fastify routes that kick off OAuth, handle the redirect, and call the API with the embedded SDK output.

routes/oauth.ts
// riposte + app come from the installation example
const sdk = riposte.createSdk()

app.get('/connect', async (_request, reply) => {
  const { authUrl } =
    await sdk.authentication.createSession({
      redirectUri: 'http://localhost:4000/oauth/callback',
    })

  reply.redirect(authUrl)
})

app.get('/oauth/callback', async (request, reply) => {
  const query = request.query as Record
  if (query.error) {
    reply.code(400).send({ error: query.error })
    return
  }

  const accounts = await sdk.accounts.list()
  reply.send({ connected: accounts.accounts?.length ?? 0 })
})
Terminal
curl --request GET   --url http://localhost:4000/riposte/api/messages   --header "Authorization: Bearer $RIPOSTE_API_KEY"
Authentication: Reuse your embedded server instance with riposte.createSdk() once it has started when you need a client inside the same process. For other services, keep RIPOSTE_API_KEY in env and send it as a bearer token.
Base URL: Requests stay inside your app at http://localhost:4000/riposte.
Manual session: For custom OAuth flows, use const { authUrl } = await riposteSdk.authentication.createSession({ redirectUri: 'https://app.example.com/oauth/callback' })

⚡ Advanced Configuration

Optional features for production-ready deployments:

🔧 Enabled Features:

📊 OpenTelemetry

📊 OpenTelemetry Integration

Enable distributed tracing and metrics collection. The config snippets above already add logging.openTelemetry; just supply the exporter details:

.env
# Add to your environment
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
OTEL_SERVICE_NAME=riposte-integration
📡 Tracing: Export spans and metrics to your collector without wrapping every handler manually.

Optional: Type your frontend with @riposte.co/api-types

Install in your frontend project with npm install @riposte.co/api-types to add lightweight type safety. This is optional, but it keeps your UI code aligned with the API responses shown in this guide.

import type { ApiResponse, Message } from '@riposte.co/api-types'

type ThreadResponse = ApiResponse['/accounts/{accountId}/threads/{threadId}']['get']

const ThreadList = ({ threads }: { threads: ThreadResponse }) => {
  return (
    <div>
      {threads.map((thread) => (
        <div key={thread.id}>{thread.subject}</div>
      ))}
    </div>
  )
}

const MessageItem = ({ message }: { message: Message }) => {
  return (
    <div>
      <div>{message.subject}</div>
      <div>{message.body}</div>
    </div>
  )
}