Skip to content
Connect an agent

AI agents

Add Flung to a website

A recipe for a coding agent: add account connecting and posting to a web app with Flung. Follow the steps in order; each file below is from a working example app and can be copied as it is.

TL;DR

QuestionAnswer
What will the site do?Show a panel where its users connect and disconnect social accounts, and post to those accounts from the server.
What must the person give me?A Flung API key that starts flung_sk_. Keep it in a server environment variable, never in code a browser loads.
Which frameworks?Next.js is shown. React with Vite and a plain page follow the same two parts: a server route that makes a connect token, and the panel that uses it.
How do I know it works?The panel lists the platforms; connecting one opens the platform's page and the account appears; a post to it returns a post id.

1. Install

bash
npm install @flung.dev/sdk @flung.dev/connect

2. Keep the key on the server

Put the key in the server's environment. Never give it a public prefix such as NEXT_PUBLIC_ or VITE_.

.env.local

bash
# A full-access Flung API key (flung_sk_...). Server only: never prefix it with NEXT_PUBLIC_.FLUNG_API_KEY=
# Optional. The API: https://api.flung.dev (the default) or https://api-preview.flung.dev.FLUNG_BASE_URL=
# The origin this app is served from, which connect tokens are made for. http://localhost:3000 when left out.APP_ORIGIN=

3. Make connect tokens on the server

Add a route the page calls. It checks who is signed in (add your app's own check), then asks Flung for a short-lived connect token for this site's origin.

app/api/connect-token/route.ts

ts
import { Flung, FlungError } from '@flung.dev/sdk'
/** * `POST /api/connect-token`: a short-lived connect token for this app's own page. The API key stays here on the server; * the token it makes can only list, connect, reconnect and disconnect accounts, from `APP_ORIGIN`, for fifteen minutes. * * In a real app, check who is signed in first, and pass their profile as `profileId` so each person sees only theirs. */export async function POST(): Promise<Response> {  const apiKey = process.env.FLUNG_API_KEY  if (apiKey === undefined || apiKey === '') return Response.json({ error: 'Set FLUNG_API_KEY in .env.local.' }, { status: 500 })  const flung = new Flung({ apiKey, ...(process.env.FLUNG_BASE_URL ? { baseUrl: process.env.FLUNG_BASE_URL } : {}) })  try {    const { token, expiresAt } = await flung.connectTokens.create({ origins: [process.env.APP_ORIGIN || 'http://localhost:3000'], expiresIn: 900 })    return Response.json({ token, expiresAt }, { headers: { 'cache-control': 'no-store' } })  } catch (error) {    const status = error instanceof FlungError ? (error.status ?? 502) : 502    return Response.json({ error: error instanceof Error ? error.message : 'Could not make a connect token.' }, { status })  }}

4. Show the panel

Add the panel to a page. It asks the route for a token, and again when one expires.

app/accounts.tsx

tsx
'use client'
import { useCallback, useState } from 'react'
import { FlungConnect } from '@flung.dev/connect/react'
/** Asks this app's server for a connect token; the panel calls it again when a token expires. */async function connectToken(): Promise<string> {  const response = await fetch('/api/connect-token', { method: 'POST' })  const body = (await response.json()) as { token?: string; error?: string }  if (!response.ok || body.token === undefined) throw new Error(body.error ?? 'Could not make a connect token.')  return body.token}
export function Accounts({ baseUrl }: { baseUrl: string | undefined }) {  const [events, setEvents] = useState<string[]>([])  const log = useCallback((line: string) => setEvents((previous) => [line, ...previous].slice(0, 5)), [])  return (    <>      <FlungConnect        token={connectToken}        baseUrl={baseUrl}        onConnect={({ accounts }) => log(`Connected ${accounts.map((account) => account.username ?? account.id).join(', ')}`)}        onDisconnect={({ account }) => log(`Disconnected ${account.username ?? account.id}`)}        onError={({ code, message }) => log(`${code}: ${message}`)}      />      {events.length > 0 && (        <ul className="events" aria-label="What happened">          {events.map((line, index) => (            <li key={`${index}-${line}`}>{line}</li>          ))}        </ul>      )}    </>  )}

5. Post from the server

With the accounts connected, post to them with the API key, from the server.

bash
curl -X POST 'https://api.flung.dev/v1/posts' \  --header "Authorization: Bearer $FLUNG_API_KEY" \  --header 'Content-Type: application/json' \  --header "Idempotency-Key: $(uuidgen)" \  --data '{  "content": "Launching today.",  "accountIds": [    "acct_aaaaaaaaaaaaaaaaaaaaaaaa"  ],  "platformOverrides": {    "x": {      "content": "Launching today. #launch"    }  },  "variables": {    "product": "Flung"  }}'

6. Hear what happened

Optionally, register a webhook endpoint and verify each event.

ts
export async function POST(request: Request): Promise<Response> {  const body = await request.text()  const event = await verifyWebhook({ body, headers: request.headers, secret: process.env.FLUNG_WEBHOOK_SECRET! })  if (event.type === 'post.failed') console.warn(`Post ${event.data.post.id} failed`)  return new Response(null, { status: 204 })}

Checks before you finish

  • FLUNG_API_KEY appears only in server code and the server's environment.
  • The connect-token route is behind the app's own sign-in.
  • APP_ORIGIN (or the origin you pass) is the address the page is served from, or the API refuses the panel's calls.
  • Every POST that creates something sends an Idempotency-Key; the SDK does this for you.

Other frameworks

FrameworkRead
React with ViteAdd account connecting to your site
A plain page, no frameworkAdd account connecting to your site
Anything elseCall the REST API: API reference