Documentation
Everything you need to integrate Filipino profanity detection into your application.
Quick Start
Integrate profanity detection in two lines of code.
/api/profanityFetch profanity words with optional filtering by language and search.
Parameters
filipino, regional, or allconst response = await fetch('http://localhost:3000/api/profanity?type=all&page=1&limit=50');
const data = await response.json();/api/checkCheck any text for profanity and receive matched words with details.
Request Body
{ "text": "your text here" }const response = await fetch('http://localhost:3000/api/check', {
method: 'POST',
headers: { Content-Type: 'application/json' },
body: JSON.stringify({ text: 'your text here' }),
});
const data = await response.json();/api/maskMask profanity words in text with asterisks or custom characters.
Request Body
{ "text": "your text here", "maskChar": "*", "partial": true }const response = await fetch('http://localhost:3000/api/mask', {
method: 'POST',
headers: { Content-Type: 'application/json' },
body: JSON.stringify({
text: 'You are a gago',
maskChar: '*',
partial: true
}),
});
const data = await response.json();/api/contributeSubmit a new profanity word for review.
Request Body
{ "word": "new-word", "language": "filipino" }const response = await fetch('http://localhost:3000/api/contribute', {
method: 'POST',
headers: { Content-Type: 'application/json' },
body: JSON.stringify({
word: 'new-word',
language: 'filipino',
email: 'user@example.com' // optional
}),
});
const data = await response.json();Python
import requests
response = requests.get('http://localhost:3000/api/profanity?type=all')
data = response.json()API Reference
GET /api/health
HealthCheck API health status and database connectivity.
Example Request
curl http://localhost:3000/api/healthResponse (200 OK)
{
"status": "ok",
"timestamp": "2025-01-19T12:00:00.000Z",
"uptime": 3600.5,
"database": {
"connected": true,
"wordCount": "310+"
},
"version": "1.0.0",
"responseTime": "12ms"
}Response (503 Degraded)
{
"status": "degraded",
"database": {
"connected": false,
"wordCount": 0
}
}GET /api/profanity
Fetch profanity words with optional filtering and pagination.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | No | Filter by language: filipino, regional, all |
word | string | No | Search for a specific word |
page | integer | No | Page number (default: 1) |
limit | integer | No | Items per page (default: 50, max: 200) |
Example Requests
# Fetch all profanity words (first page)
curl http://localhost:3000/api/profanity
# Fetch with pagination
curl "http://localhost:3000/api/profanity?page=1&limit=25"
# Fetch only Filipino profanity
curl http://localhost:3000/api/profanity?type=filipino
# Search for a specific word
curl "http://localhost:3000/api/profanity?word=gago"Response
{
"success": true,
"type": "all",
"count": 50,
"source": "database",
"pagination": {
"page": 1,
"limit": 50,
"total": 310,
"totalPages": 7,
"hasNext": true,
"hasPrev": false
},
"data": [
{
"word": "abnormal",
"language": "filipino",
"region": null,
"severity": "medium"
}
]
}GET /api/profanity/base
Fetch base profanity words without leetspeak variants. Useful when you only need the core word list.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | No | Filter by language: filipino, regional, all |
word | string | No | Search for a specific word |
page | integer | No | Page number (default: 1) |
limit | integer | No | Items per page (default: 50, max: 200) |
Example Requests
# Fetch all base words (no variants)
curl http://localhost:3000/api/profanity/base
# Fetch only Filipino base words
curl http://localhost:3000/api/profanity/base?type=filipino
# Fetch only Regional base words
curl http://localhost:3000/api/profanity/base?type=regional
# Search for a specific word
curl "http://localhost:3000/api/profanity/base?word=gago"
# Paginate results
curl "http://localhost:3000/api/profanity/base?page=1&limit=25"Response
{
"success": true,
"type": "all",
"count": 50,
"source": "database",
"pagination": {
"page": 1,
"limit": 50,
"total": 310,
"totalPages": 7,
"hasNext": true,
"hasPrev": false
},
"data": [
{
"word": "gago",
"language": "filipino",
"region": null,
"severity": "medium"
}
]
}Unlike /api/profanity, this endpoint does not include the variants field. Use this when you only need the base word list without leetspeak obfuscations.
POST /api/check
Check if a text contains profanity.
Request Body
{
"text": "Sample text to check"
}Example Request
curl -X POST http://localhost:3000/api/check \
-H "Content-Type: application/json" \
-d '{"text": "This text contains gago"}'Response
{
"success": true,
"hasProfanity": true,
"count": 1,
"data": [
{
"word": "gago",
"language": "filipino",
"region": null,
"severity": "medium"
}
]
}POST /api/check/batch
NewCheck multiple texts for profanity in a single request.
Request Body
{
"texts": [
"First text to check",
"Second text to check",
"Third text to check"
]
}Maximum 10 texts per request. Each text must not exceed 5,000 characters.
Example Request
curl -X POST http://localhost:3000/api/check/batch \
-H "Content-Type: application/json" \
-d '{"texts": ["Hello world", "You are gago"]}'Response
{
"success": true,
"totalTexts": 2,
"textsWithProfanity": 1,
"results": [
{
"text": "Hello world",
"hasProfanity": false,
"count": 0,
"data": []
},
{
"text": "You are gago",
"hasProfanity": true,
"count": 1,
"data": [
{
"word": "gago",
"language": "filipino",
"region": null,
"severity": "medium"
}
]
}
]
}POST /api/mask
NewMask profanity words in text with asterisks or custom characters.
Request Body
| Parameter | Type | Default | Description |
|---|---|---|---|
text | string | required | Text to mask (max 10,000 characters) |
maskChar | string | * | Single character to use for masking |
partial | boolean | true | Keep first letter visible (e.g., g***) |
Example Request
curl -X POST http://localhost:3000/api/mask \
-H "Content-Type: application/json" \
-d '{"text": "You are a gago", "maskChar": "*", "partial": true}'Response
{
"success": true,
"original": "You are a gago",
"masked": "You are a g***",
"matchCount": 1,
"matches": ["gago"],
"details": [
{
"word": "gago",
"start": 10,
"end": 14,
"original": "gago",
"masked": "g***"
}
]
}GET /api/variants
NewFetch leetspeak variants for profanity words. Detects intentionally obfuscated text like g4g0 for gago.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
word | string | No | Filter by exact word (e.g., gago) |
search | string | No | Search words by partial match |
page | integer | No | Page number (default: 1) |
limit | integer | No | Items per page (default: 50, max: 200) |
Example Request
# Fetch all words with variants
curl http://localhost:3000/api/variants
# Fetch variants for a specific word
curl "http://localhost:3000/api/variants?word=gago"
# Search for words matching a pattern
curl "http://localhost:3000/api/variants?search=gag"Response
{
"success": true,
"count": 1,
"source": "database",
"pagination": {
"page": 1,
"limit": 50,
"total": 109,
"totalPages": 3,
"hasNext": true,
"hasPrev": false
},
"data": [
{
"word": "gago",
"variants": [
"6460", "6490", "g4g0", "g4go",
"g@g0", "g@go", "gag0", "gaaago"
]
}
]
}GET /api/variants/lookup
NewCheck if text contains any known leetspeak variants. Useful for detecting obfuscated profanity.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Text to check (max 10,000 characters) |
Example Request
curl "http://localhost:3000/api/variants/lookup?text=g4g0+ka+talaga"Response
{
"success": true,
"hasMatch": true,
"matchCount": 1,
"data": [
{
"variant": "g4g0",
"word": "gago",
"position": 0
}
],
"source": "database"
}POST Method
You can also use POST with a JSON body:
curl -X POST http://localhost:3000/api/variants/lookup \
-H "Content-Type: application/json" \
-d '{"text": "g4g0 ka talaga"}'GET /api/stats
NewGet statistics about the profanity word database.
Example Request
curl http://localhost:3000/api/statsResponse
{
"success": true,
"total": "310+",
"byLanguage": {
"filipino": {
"count": "110+",
"percentage": 35
},
"regional": {
"count": "200+",
"percentage": 65
}
},
"bySeverity": {
"low": 0,
"medium": "310+",
"high": 0
},
"byRegion": {
"none": "110+",
"visayan": "200+"
},
"source": "database"
}POST /api/contribute
NewSubmit a new profanity word for review. Submitted words are reviewed by admins before being added to the database.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
word | string | Yes | The profanity word to submit (min 2 characters) |
language | string | Yes | Language category: filipino or regional |
region | string | If regional | Regional dialect (e.g., Visayan, Ilokano, Bicolano) |
email | string | No | Email to notify when word is added |
Example Request
curl -X POST http://localhost:3000/api/contribute \
-H "Content-Type: application/json" \
-d '{
"word": "new-word",
"language": "filipino",
"email": "user@example.com"
}'Response (201 Created)
{
"success": true,
"message": "Word submitted for review"
}Error Response (400 Bad Request)
{
"success": false,
"error": "Word and language are required"
}Error Responses
{
"success": false,
"error": "Invalid type parameter. Use: filipino, regional, or all"
}Code Examples
JavaScript (Fetch)
async function getData() {
try {
const response = await fetch("http://localhost:3000/api/profanity?type=all");
if (!response.ok) {
throw new Error("HTTP error! Status: " + response.status);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error("Error fetching data:", error);
}
}
getData();Python
import requests
try:
response = requests.get("http://localhost:3000/api/profanity?type=all")
response.raise_for_status()
data = response.json()
print(data)
except requests.exceptions.RequestException as e:
print("Error fetching data:", e)Rate Limiting
All API endpoints are rate-limited to prevent abuse. Rate limits are applied per IP address.
| Endpoint | Limit | Window |
|---|---|---|
GET /api/profanity | 60 requests | 1 minute |
GET /api/stats | 60 requests | 1 minute |
GET /api/health | No limit | N/A |
POST /api/check | 30 requests | 1 minute |
POST /api/mask | 30 requests | 1 minute |
POST /api/check/batch | 20 requests | 1 minute |
GET /api/variants | 60 requests | 1 minute |
GET /api/variants/lookup | 30 requests | 1 minute |
POST /api/contribute | 10 requests | 1 minute |
Response Headers
Every rate-limited response includes these headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed per window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Retry-After | Seconds until you can retry (only on 429) |
Rate Limit Exceeded
When you exceed the rate limit, you'll receive a 429 status code with a Retry-After header indicating how many seconds to wait.
Example
# Check rate limit headers
curl -I http://localhost:3000/api/profanity
# Response headers:
# X-RateLimit-Limit: 60
# X-RateLimit-Remaining: 59
# X-RateLimit-Reset: 1705658460Setup Guide
Prerequisites
- Node.js 18+
- npm or yarn
- Turso account (optional for local development)
Installation
1. Clone the repository
git clone <repository-url>
cd filipino_profanity_api2. Install dependencies
npm install3. Create environment file
cp .env.example .envEnvironment Variables
Edit .env file with your Turso credentials:
TURSO_DATABASE_URL=libsql://your-database-name.turso.io
TURSO_AUTH_TOKEN=your-auth-token-hereFor local development without Turso, the API will automatically use JSON fallback.
Building for Production
npm run build
npm startDatabase Setup (Optional)
To use Turso database instead of JSON fallback:
turso db create filipino-profanityturso db show filipino-profanity --url
turso auth token.env file with these valuesnpx tsx scripts/seed.tsDatabase
Schema
The profanity table stores words with language and regional information.
CREATE TABLE profanity (id INTEGER PRIMARY KEY AUTOINCREMENT, word TEXT NOT NULL, language TEXT NOT NULL, region TEXT, severity TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP);Variants Table
Stores leetspeak variants for each profanity word.
CREATE TABLE word_variants (id INTEGER PRIMARY KEY AUTOINCREMENT, profanity_id INTEGER NOT NULL, word TEXT NOT NULL, variant TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (profanity_id) REFERENCES profanity(id));Fields
| Field | Type | Description |
|---|---|---|
id | INTEGER | Primary key, auto-incrementing |
word | TEXT | The profanity word (required) |
language | TEXT | Language category: filipino or regional |
region | TEXT | Regional dialect (e.g., visayan) |
severity | TEXT | Severity level: low, medium, high |
created_at | DATETIME | Timestamp when word was added |
Seeding Process
The seed script populates the database from JSON files:
api/pure_filipino.json— Filipino profanity wordsapi/regional.json— Regional dialect profanity wordsdocs/leetspeak/filipino_variants.json— Leetspeak variants
# Seed profanity words
npx tsx scripts/seed.ts
# Seed leetspeak variants
npx tsx scripts/seed-variants.tsThe scripts create tables, check for existing data, and insert all words and variants.
Migration Guide
Adding New Words
Add words to the appropriate JSON file, then re-run the seed script:
npx tsx scripts/seed.tsManual Insert
INSERT INTO profanity (word, language, region, severity)
VALUES ('new-word', 'filipino', NULL, 'medium');Query Examples
-- Get all Filipino profanity
SELECT * FROM profanity WHERE language = 'filipino';
-- Get all regional profanity from Visayas
SELECT * FROM profanity WHERE language = 'regional' AND region = 'visayan';
-- Search for a specific word
SELECT * FROM profanity WHERE word LIKE '%gago%';Fallback Behavior
If the database connection fails or the table doesn't exist, the API automatically falls back to serving data from the JSON files. This ensures the API remains functional even without database configuration.
Features
Core Features
Profanity Fetching
Filter by language type (Filipino, Regional, All) and search for specific words.
Profanity Detection
Real-time text analysis that identifies profanity matches with metadata.
Text Masking
Mask profanity words with asterisks or custom characters. Partial masking keeps first letter visible.
Leetspeak Variants
8,000+ leetspeak variants to detect obfuscated profanity like g4g0, g@g0, 6460.
Variant Lookup
Check if text contains any known leetspeak variants for bypass detection.
Batch Checking
Check multiple texts for profanity in a single request (up to 10 texts).
Word Contribution
Submit new profanity words for review. Community-driven word database expansion.
Health Check
Monitor API health status and database connectivity.
Statistics
Get word counts by language, severity, and region with variant totals.
Rate Limiting
Built-in rate limiting with clear headers and retry guidance.
Pagination
Paginated responses for large datasets with metadata.
Technology Stack
| Component | Technology |
|---|---|
| Framework | Next.js 16+ |
| Styling | Tailwind CSS v4 |
| Icons | Lucide React |
| Database | Turso (libSQL) |
| API | Next.js Route Handlers |
| Language | TypeScript |