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
.envfiles. - 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.
| 1 | import crypto from "node:crypto"; |
| 2 | |
| 3 | export 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.
| 1 | import { z } from "zod"; |
| 2 | |
| 3 | export 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.