curl --request POST \
--url https://app.loice.ai/api/v1/name/parse/batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"names": [
"Smith, John",
"Cher",
"PODSEKIN Igor"
]
}
'const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({names: ['Smith, John', 'Cher', 'PODSEKIN Igor']})
};
fetch('https://app.loice.ai/api/v1/name/parse/batch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const url = 'https://app.loice.ai/api/v1/name/parse/batch';
const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({names: ['Smith, John', 'Cher', 'PODSEKIN Igor']})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));import requests
url = "https://app.loice.ai/api/v1/name/parse/batch"
payload = { "names": ["Smith, John", "Cher", "PODSEKIN Igor"] }
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"data": {
"results": [
{
"data": {
"first": "John",
"last": "Smith",
"given": "John",
"surname": "Smith",
"nickname": null,
"source": "model",
"confidence": 0.997,
"bothOrders": false,
"charged": true,
"pointsCharged": 1,
"replay": false
}
},
{
"error": {
"code": "invalid_input",
"message": "The name cannot be split into a given name and a surname"
}
},
{
"data": {
"first": "Igor",
"last": "PODSEKIN",
"given": "Igor",
"surname": "PODSEKIN",
"nickname": null,
"source": "model",
"confidence": 0.99,
"bothOrders": false,
"charged": true,
"pointsCharged": 1,
"replay": false
}
}
],
"pointsCharged": 2,
"replay": false,
"balance": {
"available": 98,
"reserved": 0,
"granted": 100
}
}
}{
"error": {
"code": "validation_error",
"message": "Idempotency-Key is required for a batch"
}
}{
"error": {
"code": "validation_error",
"message": "<string>",
"retryAfterSeconds": 123
}
}{
"error": {
"code": "insufficient_credits",
"message": "Insufficient credits",
"meta": {
"required": 3,
"available": 2,
"shortfall": 1
}
}
}{
"error": {
"code": "validation_error",
"message": "<string>",
"retryAfterSeconds": 123
}
}{
"error": {
"code": "validation_error",
"message": "<string>",
"retryAfterSeconds": 123
}
}{
"error": {
"code": "validation_error",
"message": "<string>",
"retryAfterSeconds": 123
}
}{
"error": {
"code": "validation_error",
"message": "<string>",
"retryAfterSeconds": 123
}
}Parse a list of names
Parses 1 to 100 names in one request, exactly as POST /api/v1/name/parse parses one, and answers one result per name in input order: { data } for an answered name, { error: { code, message } } for a refused one (invalid_input for a name that does not split, validation_error for a blank or over-long one). Each answered name is billed on its own; refused names cost nothing. The Idempotency-Key header is REQUIRED: each answered row is recorded under the key and its position, so retrying the same batch with the same key replays every answered row for free. Before any row runs, the request is refused whole when the key was used for a different batch (409) or when the workspace cannot pay one answer for every row that is not a replay (402). Nothing about the names is stored or logged. API key only; one batch counts once against its own per-workspace budget.
Billing
- charged per answered row, each its own operation — never for a refused row, a refused request or a replayed row.
The current cost is shown in the app under Settings → Billing and in the live GET /api/v1/openapi.json. Calls that end in a system or provider error (HTTP 500) or are rate limited (HTTP 429) are not billed. The charged and pointsCharged fields of the response state what this call actually consumed.
curl --request POST \
--url https://app.loice.ai/api/v1/name/parse/batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"names": [
"Smith, John",
"Cher",
"PODSEKIN Igor"
]
}
'const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({names: ['Smith, John', 'Cher', 'PODSEKIN Igor']})
};
fetch('https://app.loice.ai/api/v1/name/parse/batch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const url = 'https://app.loice.ai/api/v1/name/parse/batch';
const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({names: ['Smith, John', 'Cher', 'PODSEKIN Igor']})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));import requests
url = "https://app.loice.ai/api/v1/name/parse/batch"
payload = { "names": ["Smith, John", "Cher", "PODSEKIN Igor"] }
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"data": {
"results": [
{
"data": {
"first": "John",
"last": "Smith",
"given": "John",
"surname": "Smith",
"nickname": null,
"source": "model",
"confidence": 0.997,
"bothOrders": false,
"charged": true,
"pointsCharged": 1,
"replay": false
}
},
{
"error": {
"code": "invalid_input",
"message": "The name cannot be split into a given name and a surname"
}
},
{
"data": {
"first": "Igor",
"last": "PODSEKIN",
"given": "Igor",
"surname": "PODSEKIN",
"nickname": null,
"source": "model",
"confidence": 0.99,
"bothOrders": false,
"charged": true,
"pointsCharged": 1,
"replay": false
}
}
],
"pointsCharged": 2,
"replay": false,
"balance": {
"available": 98,
"reserved": 0,
"granted": 100
}
}
}{
"error": {
"code": "validation_error",
"message": "Idempotency-Key is required for a batch"
}
}{
"error": {
"code": "validation_error",
"message": "<string>",
"retryAfterSeconds": 123
}
}{
"error": {
"code": "insufficient_credits",
"message": "Insufficient credits",
"meta": {
"required": 3,
"available": 2,
"shortfall": 1
}
}
}{
"error": {
"code": "validation_error",
"message": "<string>",
"retryAfterSeconds": 123
}
}{
"error": {
"code": "validation_error",
"message": "<string>",
"retryAfterSeconds": 123
}
}{
"error": {
"code": "validation_error",
"message": "<string>",
"retryAfterSeconds": 123
}
}{
"error": {
"code": "validation_error",
"message": "<string>",
"retryAfterSeconds": 123
}
}Authorizations
Workspace API key (loice_sk_ + 48 hex characters), created under Settings → API Keys. Sent as Authorization: Bearer loice_sk_…. Invalid, missing, or expired keys are rejected with 401 before any billable work happens.
Headers
REQUIRED, 1–255 printable ASCII characters, scoped to your workspace. Each answered row is its own billed operation under this key and the row’s position, so retrying the same batch with the same key replays every answered row for free. The same key with a different batch (any change to names or spelling) is refused whole with 409 idempotency_conflict before any row runs. The key is stored as sent: never put a name or other personal data in it.
1 - 255Body
1 to 100 names, each answered in order. A non-string element refuses the whole request; a blank name or one longer than 256 characters is that row’s validation_error.
1 - 100 elementsas-written (default) returns the words as you sent them, cleaned of honorifics, credentials and asides. folded returns the key spelling: lower case, diacritics removed (José Núñez → jose / nunez).
as-written, folded Response
One result per submitted name, in input order. pointsCharged is the sum of the rows; replay is true when every answered row replayed an earlier call with this key.
Show child attributes
Show child attributes

