SQL Formatter API
Pretty-print SQL queries with consistent indentation and keyword case for MySQL, PostgreSQL, SQL Server, Oracle, BigQuery and more, or compact them.
The SQL formatter rewrites a query with one clause per line, indented column lists and joins, and a consistent case for keywords, data types and functions (keyword_case upper, lower or preserve). Choose the dialect so its syntax is understood: mysql, mariadb, postgresql, sqlite, tsql (SQL Server), plsql (Oracle), bigquery, snowflake, redshift, spark, db2, trino, clickhouse or standard sql.
Tune the layout with indent (1–8 spaces) or tabs=true, expression_width (how long a parenthesised expression may stay on one line), logical_operator_newline (before or after AND / OR) and lines_between_queries for scripts with several statements. String literals and comments are kept.
minify=true does the opposite: comments are removed and whitespace outside quotes collapsed, for logs or query strings. A query that cannot be parsed returns invalid_sql with the position of the problem.
Parameters
| Name | In | Type | Required | Default | |
|---|---|---|---|---|---|
sql | body|query | string | yes | The SQL (max 500,000 characters). | |
dialect | body|query | string | no | sql | sql, mysql, mariadb, postgresql, sqlite, tsql, plsql, bigquery, snowflake, redshift, spark, db2, trino, clickhouse. |
keyword_case | body|query | string | no | upper | upper, lower or preserve. |
indent | body|query | number | no | 2 | Spaces per level (1–8). |
tabs | body|query | boolean | no | false | Indent with tabs. |
expression_width | body|query | number | no | 50 | Max width of a parenthesised expression on one line (20–200). |
logical_operator_newline | body|query | string | no | before | Line break before or after AND / OR. |
lines_between_queries | body|query | number | no | 1 | Blank lines between statements (0–5). |
minify | body|query | boolean | no | false | Compact the SQL instead of formatting it. |
Example
curl -X POST "https://apibox.io.vn/v1/sql-format" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sql":"select u.id, u.name, count(o.id) as orders from users u left join orders o on o.user_id = u.id where u.city = '\''Hà Nội'\'' and o.total > 100000 group by u.id, u.name order by orders desc limit 10","dialect":"postgresql"}'const res = await fetch('https://apibox.io.vn/v1/sql-format', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"sql": "select u.id, u.name, count(o.id) as orders from users u left join orders o on o.user_id = u.id where u.city = 'Hà Nội' and o.total > 100000 group by u.id, u.name order by orders desc limit 10",
"dialect": "postgresql"
}),
});
const data = await res.json();
console.log(data);import requests
res = requests.post(
"https://apibox.io.vn/v1/sql-format",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"sql": "select u.id, u.name, count(o.id) as orders from users u left join orders o on o.user_id = u.id where u.city = 'Hà Nội' and o.total > 100000 group by u.id, u.name order by orders desc limit 10", "dialect": "postgresql"},
timeout=30,
)
print(res.json())<?php
$ch = curl_init('https://apibox.io.vn/v1/sql-format');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"sql":"select u.id, u.name, count(o.id) as orders from users u left join orders o on o.user_id = u.id where u.city = \'Hà Nội\' and o.total > 100000 group by u.id, u.name order by orders desc limit 10","dialect":"postgresql"}',
]);
$response = curl_exec($ch);
print_r(json_decode($response, true));Response
{
"dialect": "postgresql",
"formatted": "SELECT\n u.id,\n u.name,\n COUNT(o.id) AS orders\nFROM\n users u\n LEFT JOIN orders o ON o.user_id = u.id\nWHERE\n u.city = 'Hà Nội'\n AND o.total > 100000\nGROUP BY\n u.id,\n u.name\nORDER BY\n orders DESC\nLIMIT\n 10",
"statements": 1,
"length": {
"input": 191,
"output": 213
}
}
Use cases
- Readable SQL in code reviews and documentation
- Normalise queries before storing them in a repository
- Format queries captured from slow-query logs
- Compact SQL for logs and config files
FAQ
Does it check that my SQL is valid?
Only its syntax as far as formatting needs; table and column names are not checked against a database.
Are comments kept?
Yes when formatting. minify=true removes them.
Which dialect should I choose?
The one of your database; it matters for quoting (backticks, [brackets]) and specific keywords. sql works for standard queries.
Related APIs
UUID Generator
Generate up to 1,000 UUID v4, time-ordered UUID v7, ULID, Nano ID or random hex IDs per request. Secure randomness, optional uppercase.
⏱Cron Expression Parser
Validate a cron expression and get its next run times in any timezone, with a plain-English description. Supports 5, 6 and 7-field cron syntax.
🕒Time & Timezone Converter
Get the current time in any timezone, convert between timezones and Unix timestamps (seconds or ms), with UTC offset and weekday for up to 30 zones.