Clean

Clean and normalise a text

POST/v1/clean/string

View as Markdown

Runs the chosen operations one after the other, in the order listed: HTML to plain text, line breaks to br and back, remove line breaks, collapse whitespace, trim, remove diacritics, slugify (URL-safe text for names) and change case.

Request body

Name Type Required Description
text string yes The text
operations array of one of: html_to_text, line_breaks_to_br, br_to_line_breaks, remove_line_breaks, collapse_whitespace, trim, remove_diacritics, slugify, lower, upper, title yes What to do, run one after the other in the order listed
line_break_replacement string no For remove_line_breaks: what each line break becomes (default " ")

Example request

A request body that works, as JSON.

{
  "text": " Café Résumé\n Quarterly ",
  "operations": [
    "remove_diacritics",
    "collapse_whitespace",
    "trim",
    "slugify"
  ]
}

Code samples

Replace YOUR_TOKEN with your access token.

curl

curl -X POST 'https://api.skillfulsardine.com/v1/clean/string' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "text": " Café Résumé\n Quarterly ",
  "operations": [
    "remove_diacritics",
    "collapse_whitespace",
    "trim",
    "slugify"
  ]
}'

PowerShell

$body = @'
{
  "text": " Café Résumé\n Quarterly ",
  "operations": [
    "remove_diacritics",
    "collapse_whitespace",
    "trim",
    "slugify"
  ]
}
'@
$response = Invoke-RestMethod -Method Post -Uri 'https://api.skillfulsardine.com/v1/clean/string' `
  -Headers @{ Authorization = 'Bearer YOUR_TOKEN' } `
  -ContentType 'application/json; charset=utf-8' `
  -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
$response | ConvertTo-Json -Depth 10

Python

import requests

payload = {
    "text": " Café Résumé\n Quarterly ",
    "operations": [
        "remove_diacritics",
        "collapse_whitespace",
        "trim",
        "slugify",
    ],
}

response = requests.post(
    "https://api.skillfulsardine.com/v1/clean/string",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json=payload,
    timeout=30,
)
print(response.json())

JavaScript

const response = await fetch("https://api.skillfulsardine.com/v1/clean/string", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "text": " Café Résumé\n Quarterly ",
  "operations": [
    "remove_diacritics",
    "collapse_whitespace",
    "trim",
    "slugify"
  ]
}),
});
const result = await response.json();
console.log(result);

Node

// Node 18 or later. Save as call.mjs and run: API_TOKEN=... node call.mjs
const token = process.env.API_TOKEN;

const response = await fetch("https://api.skillfulsardine.com/v1/clean/string", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "text": " Café Résumé\n Quarterly ",
  "operations": [
    "remove_diacritics",
    "collapse_whitespace",
    "trim",
    "slugify"
  ]
}),
});
const result = await response.json();
console.log(result);

Rust

// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }, serde_json = "1"
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let body: serde_json::Value = serde_json::from_str(r#"{
  "text": " Café Résumé\n Quarterly ",
  "operations": [
    "remove_diacritics",
    "collapse_whitespace",
    "trim",
    "slugify"
  ]
}"#)?;
    let response = reqwest::blocking::Client::new()
        .post("https://api.skillfulsardine.com/v1/clean/string")
        .bearer_auth("YOUR_TOKEN")
        .json(&body)
        .send()?;
    println!("{}", response.text()?);
    Ok(())
}

Swift

import Foundation

var request = URLRequest(url: URL(string: "https://api.skillfulsardine.com/v1/clean/string")!)
request.httpMethod = "POST"
request.setValue("Bearer YOUR_TOKEN", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(#"""
{
  "text": " Café Résumé\n Quarterly ",
  "operations": [
    "remove_diacritics",
    "collapse_whitespace",
    "trim",
    "slugify"
  ]
}
"""#.utf8)

let (data, _) = try await URLSession.shared.data(for: request)
print(String(decoding: data, as: UTF8.self))

Response

The fields inside data of a successful response.

Name Type Required Description
text string yes The text after every operation

Example response

A real answer from the operation, as JSON. The fields in the table above are inside data.

{
  "data": {
    "text": "cafe-resume-quarterly"
  },
  "errors": null,
  "meta": {
    "request_id": "4fe334c6-346f-48c7-998d-c63411983105",
    "timestamp": "2026-10-27T07:19:42.067405Z",
    "version": "2026-03-26"
  },
  "pagination": null
}

Responses

Status When it happens
200 Successful Response
400 The body respects the operation schema, but the use case rejected it. Each problem is one ApiError entry
413 The request is larger than the request size limit of the API allows
422 The body does not respect the operation schema. Each problem is one ApiError entry with the code validation_error
500 Something failed inside the server and was not an input problem. The same envelope, errors may be empty