Tutorials

Security

Apps built on the FrontRow API handle private fan conversations, payment-adjacent data, and creator credentials. The same patterns that secure any API integration apply here, plus a few specifics for FrontRow’s key model and webhook signing.

Code samples below use Node.js / TypeScript. The patterns translate directly to any language with HMAC and a schema validator.

01

Authentication vs. authorization

Two questions, asked in order, on every request: who are you? (authentication) and what are you allowed to do? (authorization). FrontRow handles authentication when it validates your API key. Your application is responsible for authorization — checking that the requester is permitted to perform the action they’re asking for.

For end-user authentication on top of FrontRow data (e.g. an agency dashboard signed into by managers), delegate to a dedicated provider — Clerk, Auth0, Supabase Auth — or a framework like Auth.js or BetterAuth. Don’t roll your own password storage.

02

Protecting API keys

API keys are bearer credentials: anyone holding the string can act as the creator. Treat them like database passwords.

  • Store keys in a secrets manager (AWS Secrets Manager, GCP Secret Manager, Vercel/Netlify env vars). Never commit .env files.
  • Use the most-restrictive scopes available. A read-only analytics tool should not have write:chat.
  • Rotate on any suspicion of leak — and on staff changes if a human ever saw the key. Rotation in the FrontRow dashboard invalidates the old key immediately.
  • Never expose a key to a browser. All FrontRow calls must originate from a server you control.

03

Verifying webhook signatures

Every webhook FrontRow sends is signed with HMAC-SHA256 using your endpoint’s signing secret. An unsigned or incorrectly-signed request must be rejected — otherwise an attacker who guesses your URL can forge events.

Compute the HMAC over the raw request body (not a re-serialized object), then compare with crypto.timingSafeEqual to avoid timing oracles.

ts · verify.ts
1import crypto from "node:crypto";
2 
3export function verifyWebhook(
4 rawBody: Buffer,
5 signature: string | undefined,
6 secret: string
7): boolean {
8 if (!signature) return false;
9 
10 const expected = crypto
11 .createHmac("sha256", secret)
12 .update(rawBody)
13 .digest("hex");
14 
15 const a = Buffer.from(signature, "hex");
16 const b = Buffer.from(expected, "hex");
17 
18 if (a.length !== b.length) return false;
19 return crypto.timingSafeEqual(a, b);
20}

Also reject events where X-FrontRow-Timestamp is more than five minutes old. This prevents replay attacks even if a signed payload is captured later.

04

HTTPS and hosting

The FrontRow API only accepts TLS-encrypted requests. The same should apply to your endpoints — webhook URLs over plain HTTP will be refused at registration time.

Managed platforms (Vercel, Netlify, Fly.io, Render) handle TLS termination and certificate renewal automatically. If you’re self-hosting, use Caddy or a reverse proxy with Let’s Encrypt.

05

Input validation

Validate every payload at the boundary, even ones from FrontRow. Use a schema library (Zod, Yup, Pydantic) so unexpected shapes fail closed rather than propagating into your domain logic.

ts · event-schema.ts
1import { z } from "zod";
2 
3export const MessageReceived = z.object({
4 event: z.literal("message.received"),
5 conversationId: z.string(),
6 message: z.object({
7 id: z.string(),
8 text: z.string().max(10000),
9 from: z.object({
10 handle: z.string(),
11 verified: z.boolean(),
12 }),
13 }),
14});

06

Rate limits and abuse

FrontRow returns 429 Too Many Requests with a Retry-After header when limits are exceeded. Honor it with exponential backoff — retrying immediately compounds the problem and risks a temporary key suspension.

On the inbound side, rate-limit your webhook handler per source IP and per conversation ID so a flood of replays cannot exhaust your worker pool.

07

Logging and error handling

Log enough to debug; never log secrets. Strip Authorization headers, API keys, and webhook signing secrets before they touch your logging pipeline. Many incident reports start with “the key was in our log archive.”

Return generic 4xx/5xx responses to clients. Detailed errors (stack traces, internal IDs) belong in your monitoring system, not the response body.

08

Dependencies and headers

Treat dependency updates as a security task. Tools like npm audit, Dependabot, Snyk, and Socket.dev catch known CVEs before they reach production. Keep your runtime (Node, Python, Bun) on a supported version.

For any dashboard you build on top of the API, set the standard security headers: Content-Security-Policy, Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options. Most frameworks ship sane defaults; verify they’re actually on in production.

09

Scanning and pen-testing

Automated scanners catch the easy stuff. Run one against any public-facing dashboard before going live — OWASP ZAP and Burp Suite (Community) are free; Intruder.io, Invicti, and Acunetix are paid options with broader coverage. For high-value integrations, schedule an annual third-party penetration test.

Reporting a vulnerability

If you believe you’ve found a security issue in the FrontRow API, email security@frontrow.center. Please don’t open a public issue. We respond to all reports within 48 hours.