Server SDK
Use @formtress/server in your server-side code to check submissions for spam before storing or acting on them. No data is saved — the filter endpoint only returns a spam score.
Install
Section titled “Install”npm install @formtress/serverpnpm add @formtress/serveryarn add @formtress/serverbun add @formtress/serverCurrent version: 0.1.0
Quick start
Section titled “Quick start”Create a Formtress client with your API key, then call filter() on every submission:
import { Formtress } from '@formtress/server'
const formtress = new Formtress({ apiKey: process.env.FORMTRESS_API_KEY!, // starts with ftk_})
const result = await formtress.filter({ ip: '1.2.3.4', headers: Object.fromEntries(request.headers), fields: [ { name: 'email', value: 'test@gmail.com', type: 'email' }, { name: 'message', value: 'Hello world', type: 'text' }, ], blockFreeEmailProviders: true,})
if (result.isSpam) { // reject the submission}How it works
Section titled “How it works”-
End-user sends a request
Section titled “End-user sends a request”The submission arrives at your server with the end-user’s IP address and request headers.
-
Call
Section titled “Call formtress.filter()”formtress.filter()The SDK forwards the IP, headers, and field values to the Formtress filter endpoint.
-
Formtress API analyzes the submission
Section titled “Formtress API analyzes the submission”The API runs rate-limiting, bot detection, and content analysis. No field values are stored! The endpoint only returns a spam score.
-
Receive the result
Section titled “Receive the result”The API responds with
{ isSpam, score, fieldErrors }. -
Accept or reject
Section titled “Accept or reject”Your server decides whether to accept the submission or reject it based on the result.
new Formtress(options)
Section titled “new Formtress(options)”Create a client instance.
| Option | Type | Required | Description |
|---|---|---|---|
apiKey | string | Yes | Your Formtress API key (ftk_…) |
formtress.filter(options)
Section titled “formtress.filter(options)”Check a submission for spam. Returns a FilterResult.
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
ip | string | Yes | — | End-user’s IP address (used for rate limiting) |
headers | Record<string,string> | Yes | — | Forwarded request headers from the end-user |
fields | FilterField[] | No | — | Field values for content-level spam detection |
blockFreeEmailProviders | boolean | No | false | Flag free email providers (e.g. gmail.com) |
FilterField
Section titled “FilterField”interface FilterField { name: string // field name, e.g. "email" value: string // field value type: string // field type, e.g. "email", "text", "url"}FilterResult
Section titled “FilterResult”| Property | Type | Description |
|---|---|---|
isSpam | boolean | Whether the submission was detected as spam |
score | number | Spam confidence score (0–1) |
rateLimited | boolean | Whether the end-user was rate limited |
fieldErrors | Record<string,string>? | Per-field spam errors, keyed by field name |
FormtressError
Section titled “FormtressError”Thrown when the API returns a non-2xx response.
| Property | Type | Description |
|---|---|---|
message | string | Error description |
status | number | HTTP status code |
body | unknown | Raw response body |
Framework examples
Section titled “Framework examples”import { fail } from '@sveltejs/kit'import { Formtress } from '@formtress/server'import type { Actions } from './$types'
export const actions: Actions = { default: async ({ request, getClientAddress }) => { const formData = await request.formData()
const formtress = new Formtress({ apiKey: process.env.FORMTRESS_API_KEY!, })
const result = await formtress.filter({ ip: getClientAddress(), headers: Object.fromEntries(request.headers), fields: [ { name: 'email', value: formData.get('email') as string, type: 'email' }, { name: 'message', value: formData.get('message') as string, type: 'text' }, ], blockFreeEmailProviders: true, })
if (result.isSpam) { return fail(403, { spam: true, result }) }
// save to DB, send email, etc. return { success: true } },}import { Formtress } from '@formtress/server'import { NextRequest, NextResponse } from 'next/server'
const formtress = new Formtress({ apiKey: process.env.FORMTRESS_API_KEY!,})
export async function POST(request: NextRequest) { const body = await request.json()
const result = await formtress.filter({ ip: request.ip || 'unknown', headers: Object.fromEntries(request.headers), fields: [ { name: 'email', value: body.email, type: 'email' }, ], })
if (result.isSpam) { return NextResponse.json({ error: 'Spam detected' }, { status: 403 }) }
// proceed with the submission return NextResponse.json({ ok: true })}import express from 'express'import { Formtress } from '@formtress/server'
const app = express()const formtress = new Formtress({ apiKey: process.env.FORMTRESS_API_KEY!,})
app.post('/contact', express.json(), async (req, res) => { const result = await formtress.filter({ ip: req.ip!, headers: req.headers as Record<string, string>, fields: [ { name: 'email', value: req.body.email, type: 'email' }, { name: 'message', value: req.body.message, type: 'text' }, ], blockFreeEmailProviders: true, })
if (result.isSpam) { return res.status(403).json({ error: 'Spam detected' }) }
// save to DB, send email, etc. res.json({ ok: true })})import { createServer } from 'node:http'import { Formtress } from '@formtress/server'
const formtress = new Formtress({ apiKey: process.env.FORMTRESS_API_KEY!,})
const server = createServer(async (req, res) => { if (req.method !== 'POST' || req.url !== '/contact') { res.writeHead(404).end() return }
let body = '' req.on('data', chunk => body += chunk) req.on('end', async () => { const data = JSON.parse(body)
const result = await formtress.filter({ ip: req.socket.remoteAddress!, headers: Object.fromEntries(Object.entries(req.headers).filter(([_, v]) => typeof v === 'string') as [string, string][]), fields: [ { name: 'email', value: data.email, type: 'email' }, ], })
if (result.isSpam) { res.writeHead(403, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ error: 'Spam detected' })) return }
res.writeHead(200, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ ok: true })) })})Endpoint
Section titled “Endpoint”If you prefer to call the API directly without the SDK:
https://app.formtress.com/public/api/v1/filterSee the API Reference for the raw HTTP contract.