Developer documentation

Build with Wordly API.

Use a server-side API key, make HTTPS requests, and track every call through a predictable credit-based billing model. This reference documents the endpoints currently available in production and clearly marks endpoints that are still being prepared.

API version v1Format JSONTransport HTTPS onlyFree balance 50 creditsOpenAPI Download schemaPostman CollectionPostman Environment

Quickstart

Create a free account, verify your email using the six-digit code, and copy the API key shown once in your developer dashboard.

  1. 1
    Create an account

    Register with only an email address and password.

  2. 2
    Verify your email

    Enter the code sent by [email protected]. Verification grants 50 free credits.

  3. 3
    Store your API key

    Copy the generated wly_live_... key and keep it in a server-side environment variable.

  4. 4
    Make a test request

    Call the account endpoint to verify authentication and see the remaining balance.

Shell
curl "https://api.wordlyenglish.com/v1/account" \
  -H "Authorization: Bearer $WORDLY_API_KEY" \
  -H "Accept: application/json"
200 response
{
  "data": {
    "message": "Authenticated",
    "credits_remaining": 50
  },
  "meta": { "lang": "en" }
}

Base URL and versioning

All production endpoints are served from the following versioned base URL:

Base URLhttps://api.wordlyenglish.com/v1

Breaking response or behavior changes will use a new path version. Additive fields may be introduced within v1, so clients should ignore response properties they do not recognize.

Authentication

Authenticated endpoints require an API key in the HTTP Authorization header using the Bearer scheme.

Authorization: Bearer wly_live_your_api_key
Do not expose API keys.

Never place a live key in browser JavaScript, public Git repositories, screenshots, logs, or a distributed mobile application. Call Wordly API from your backend and let your own application communicate with that backend.

Localized API messages

Set the response language with ?lang=tr or the standard Accept-Language header. Query parameters take precedence. Every JSON response declares the selected locale in Content-Language and meta.lang. Error codes remain stable in English for programmatic handling; only the human-readable message is localized.

curl "https://api.wordlyenglish.com/v1/account?lang=tr" \
  -H "Authorization: Bearer $WORDLY_API_KEY" \
  -H "Accept-Language: tr-TR"

Supported language codes: en, tr, de, fr, es, it, pt, nl, pl, ru, uk, ar, fa, he, hi, bn, ur, zh, ja, ko, id, ms, vi, th, sv, no, da, fi, cs, ro.

Credits and billing

Each successful metered request consumes the documented number of credits. Email-verified accounts receive 50 free credits once. Credits are deducted atomically, so concurrent requests cannot spend the same balance twice. Balance lookup through GET /v1/account is free.

OperationCredit costAvailability
GET /v1/status0Live
GET /v1/account0Live
GET /v1/words/{word}1–5Live
GET /v1/words/search1Live
GET /v1/words/random1 per wordLive
POST /v1/words/batchBased on returned recordsLive

Use GET /v1/account when you need the current balance. Other endpoint responses include the operation charge but omit the remaining balance. When the balance is insufficient, the API returns HTTP 402 and does not process the operation.

402 response
{
  "error": {
    "code": "credits_exhausted",
    "message": "Your credit balance is exhausted. Add a package or enable pay-as-you-go to continue.",
    "upgrade_url": "/app.php?page=billing"
  }
}

API key lifecycle

Create separate keys for development, staging, and production. Wordly stores only a cryptographic hash of each key; the complete value is displayed once at creation.

  • Name keys by environment or service.
  • Use environment variables or a managed secret store.
  • Revoke a key immediately if it may have been exposed.
  • Rotate keys without reusing old values.
  • Do not send keys in query strings.

Response format

Successful responses use a top-level data object and may include a meta object. Errors always use a top-level error object with a stable machine-readable code and a human-readable message.

Successful request
{
  "data": { ... },
  "meta": {
    "credits_used": 1,
    "request_id": "..."
  }
}
Failed request
{
  "error": {
    "code": "invalid_api_key",
    "message": "..."
  }
}

Keep the request_id when contacting support about a successful billed request. JSON is UTF-8 encoded and clients should send Accept: application/json.

Cache behavior

Wordly caches shared vocabulary data on the server, never API keys, account identities, balances, rate-limit state, or request identifiers. Public status and language responses advertise shared-cache lifetimes. Authenticated responses remain private, no-store; applications may cache the stable data value in their own trusted backend when appropriate.

Endpoint reference

Production endpoints

GET/v1/statusLive

Returns public service health and API version information. This endpoint does not require authentication and costs zero credits.

Example request

curl "https://api.wordlyenglish.com/v1/status" \
  -H "Accept: application/json"

200 · Success

{
  "data": { "status": "ok", "version": "v1" },
  "meta": { "lang": "en" }
}
Possible results200 Service is reachable.405 Method is not GET.429 IP request limit exceeded.
GET/v1/accountLive · 0 credits

Validates the supplied key and returns the current account balance without charging a credit.

Headers

NameRequiredDescription
AuthorizationYesBearer wly_live_...
AcceptRecommendedapplication/json

Response headers

X-Credits-Remaining is returned only by this balance endpoint.

200 · Success

{
  "data": { "message": "Authenticated", "credits_remaining": 1250 },
  "meta": { "lang": "en" }
}
Possible results200 Key accepted and balance returned.401 Missing, invalid, revoked, or suspended key.429 Rate limit exceeded.

Vocabulary endpoints

20,000+ catalog entries are live.

Every record reports its completeness as catalog, translated, or enriched. Fields that are not available are returned as null or an empty object instead of invented data.

GET /v1/words/{word}

Returns an exact word match. Use languages=tr,de,fr to return only requested translations. Catalog or translated records cost 1 credit; fully enriched profiles cost 5 credits.

curl "https://api.wordlyenglish.com/v1/words/water?languages=tr,de" \
  -H "Authorization: Bearer $WORDLY_API_KEY"

GET /v1/words/search

Search with q and optional level, part_of_speech, category, limit, and cursor. Limits range from 1 to 50. Pass meta.next_cursor into the next request.

curl "https://api.wordlyenglish.com/v1/words/search?q=app&level=advanced&limit=20" \
  -H "Authorization: Bearer $WORDLY_API_KEY"

GET /v1/words/random

Returns 1–20 random words. Filter by level, part_of_speech, or category. Each returned slot costs one credit.

POST /v1/words/batch

Looks up between 1 and 50 unique words in a single request. The response preserves request order and marks every item with found.

curl -X POST "https://api.wordlyenglish.com/v1/words/batch?lang=tr" \
  -H "Authorization: Bearer $WORDLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"words":["water","opportunity"],"languages":["tr","de"]}'

GET /v1/languages

Returns all 30 supported interface and API-message locales. Vocabulary translations are returned only when available. This endpoint is public and costs zero credits.

Rate limit

Each API key is limited to 120 accepted requests per rolling minute. Responses include X-RateLimit-Limit and X-RateLimit-Remaining. A 429 rate_limit_exceeded response includes Retry-After: 60.

GET/v1/languagesLive · 0 credits

Lists all supported interface and API-message locales. Vocabulary translations are returned only when a record contains them.

Query parameters

NameTypeRequiredRulesDescription
langstringNoSupported locale codeLanguage for human-readable messages.

Example request

curl "https://api.wordlyenglish.com/v1/languages?lang=tr"

200 · Success

{
  "data": [{
    "code": "tr",
    "name": "Türkçe",
    "message_localization": true,
    "vocabulary_translation": "when_available"
  }],
  "meta": { "count": 30, "lang": "tr" }
}
Possible results200 Locale list returned.405 Method is not GET.429 IP request limit exceeded.
GET/v1/words/{word}Live · 1–5 credits

Returns one exact vocabulary record. Catalog and translated records cost 1 credit; enriched records cost 5 credits.

Parameters

NameLocationTypeRequiredRules and meaning
wordPathstringYesExact word or slug; maximum 120 characters. URL-encode special characters.
languagesQuerystringNoComma-separated translation codes, for example tr,de,fr.
langQuerystringNoHuman-readable message language; not a vocabulary filter.

Example request

Shell
curl "https://api.wordlyenglish.com/v1/words/water?languages=tr,de" \
  -H "Authorization: Bearer $WORDLY_API_KEY" \
  -H "Accept: application/json"

200 · Success

{
  "data": {
    "id": "water",
    "word": "water",
    "part_of_speech": "noun",
    "level": "basic",
    "definition": "A clear liquid essential for life.",
    "example": "Please drink enough water every day.",
    "translations": { "tr": "su", "de": "Wasser" },
    "categories": ["nature", "daily-life"],
    "media": {
      "image_url": "https://media.example/water.webp",
      "audio_url": "https://media.example/water.mp3",
      "attribution": {}
    },
    "completeness": "enriched"
  },
  "meta": {
    "credits_used": 5,
    "request_id": "5ebac760-cdc5-4a73-a87b-22463d81483c",
    "lang": "en"
  }
}

404 · Word unavailable

{
  "error": { "code": "word_not_found", "message": "The requested word was not found." },
  "meta": { "lang": "en" }
}
Possible results200 Exact record returned.401 Invalid API key.402 Insufficient credits.404 Word not found.422 Word too long.429 Rate limit exceeded.
GET/v1/words/randomLive · 1 credit per requested slot

Returns random active words for quizzes, discovery feeds, and practice sessions.

Query parameters

NameTypeRequiredDefault / limitDescription
countintegerNo1; min 1, max 20Requested slots and credit cost.
levelstringNoExact valueLevel filter.
part_of_speech / posstringNoExact valueGrammatical-class filter.
categorystringNoExact valueCategory filter.
languagesstringNoComma-separatedTranslations to include.

Example request

curl "https://api.wordlyenglish.com/v1/words/random?count=3&level=basic&languages=tr" \
  -H "Authorization: Bearer $WORDLY_API_KEY"

200 · Success

{
  "data": [{ "id": "water", "word": "water", "part_of_speech": "noun", "level": "basic", "definition": null, "example": null, "translations": { "tr": "su" }, "categories": [], "media": { "image_url": null, "audio_url": null, "attribution": {} }, "completeness": "translated" }],
  "meta": { "credits_used": 3, "request_id": "...", "lang": "en", "count": 1 }
}
Possible results200 Random array returned.401 Invalid API key.402 Balance below requested count.429 Rate limit exceeded.
POST/v1/words/batchLive · calculated

Looks up 1–50 unique words while preserving request order. Each enriched result costs 5 credits, another found result costs 1, and the minimum request charge is 1.

Headers

NameRequiredValue
AuthorizationYesBearer wly_live_...
Content-TypeYesapplication/json
AcceptRecommendedapplication/json

JSON body

FieldTypeRequiredRulesDescription
wordsstring[]Yes1–50 items; each max 120 charsWords to resolve; duplicates are normalized and removed.
languagesstring[]NoSupported locale codesTranslations to include.

Example request

curl -X POST "https://api.wordlyenglish.com/v1/words/batch?lang=tr" \
  -H "Authorization: Bearer $WORDLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"words":["water","not-a-word"],"languages":["tr","de"]}'

200 · Success

{
  "data": [
    { "query": "water", "found": true, "word": { "id": "water", "word": "water", "part_of_speech": "noun", "level": "basic", "definition": null, "example": null, "translations": { "tr": "su", "de": "Wasser" }, "categories": [], "media": { "image_url": null, "audio_url": null, "attribution": {} }, "completeness": "translated" } },
    { "query": "not-a-word", "found": false, "word": null }
  ],
  "meta": { "credits_used": 1, "request_id": "...", "lang": "tr", "count": 2 }
}

422 · Invalid body

{
  "error": { "code": "invalid_request", "message": "Provide between 1 and 50 words." },
  "meta": { "lang": "en" }
}
Possible results200 Ordered results.401 Invalid API key.402 Insufficient credits.413 Body over 64 KB.415 Content-Type is not JSON.422 Invalid words array.429 Rate limit exceeded.

Response field reference

Every stable response variable is described below. Additive fields may appear later, so clients should ignore fields they do not recognize.

Vocabulary object

FieldTypeNullableDescription
idstringNoStable URL-safe slug.
wordstringNoCanonical English word.
part_of_speechstringYesGrammatical class.
levelstringYesLearning difficulty or catalog level.
definitionstringYesConcise English definition.
examplestringYesNatural example sentence.
phoneticstringYesPronunciation transcription when available.
translationsobject<string,string>NoLocale codes mapped to translations; may be empty.
synonymsstring[]NoAvailable synonyms.
antonymsstring[]NoAvailable antonyms.
categoriesstring[]NoLearning or semantic categories.
media.image_urlURL stringYesLearning image URL.
media.audio_urlURL stringYesPronunciation audio URL.
media.attributionobjectNoRequired media attribution metadata.
completenessenumNocatalog, translated, or enriched.

Meta object

FieldTypeWhen presentDescription
credits_usedintegerMetered responsesCredits charged by this request.
request_idUUID stringMetered successSupport and billing trace ID.
langstringAlwaysSelected message locale.
countintegerList responsesNumber of response items.
next_cursorstring or nullSearchNext page cursor; null means final page.

Error object

FieldTypeDescription
error.codestringStable machine-readable code.
error.messagestringLocalized human-readable explanation.
error.upgrade_urlstringRelative billing URL on a 402 result.
meta.langstringError-message locale.

Errors

HTTPCodeMeaningClient action
401invalid_api_keyMissing, malformed, revoked, or inactive key.Check the Bearer header or replace the key.
402credits_exhaustedThe account lacks credits for the operation.Stop retries and direct the customer to billing.
404not_foundThe requested endpoint is not available.Check the path and API version.
404word_not_foundThe requested vocabulary entry is unavailable.Check spelling or use search.
422invalid_requestA parameter or batch body is invalid.Correct the request before retrying.
405method_not_allowedThe endpoint does not accept the HTTP method.Use the documented GET or POST method.
413payload_too_largeThe JSON request body exceeds 64 KB.Reduce the batch body.
415unsupported_media_typeThe batch request is not JSON.Send Content-Type: application/json.
429rate_limit_exceededThe API key exceeded 120 requests per minute.Wait for Retry-After.
5xxserver_errorAn unexpected server-side failure.Retry with backoff; contact support if persistent.

Recommended retry policy

Do not retry 401, 402, or 404 automatically. For transient 5xx responses, use exponential backoff with jitter and a strict retry cap. Never create an unbounded retry loop because each accepted authenticated request may consume credits.

JavaScript / Node.js

const response = await fetch('https://api.wordlyenglish.com/v1/account', {
  headers: {
    Authorization: `Bearer ${process.env.WORDLY_API_KEY}`,
    Accept: 'application/json'
  }
});

const body = await response.json();
if (!response.ok) {
  throw new Error(`${body.error.code}: ${body.error.message}`);
}

console.log(body.data.credits_remaining);

Python

import os
import requests

response = requests.get(
    'https://api.wordlyenglish.com/v1/account',
    headers={
        'Authorization': f'Bearer {os.environ["WORDLY_API_KEY"]}',
        'Accept': 'application/json',
    },
    timeout=15,
)
response.raise_for_status()
print(response.json()['data']['credits_remaining'])

PHP

$curl = curl_init('https://api.wordlyenglish.com/v1/account');
curl_setopt_array($curl, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_TIMEOUT => 15,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WORDLY_API_KEY'),
    'Accept: application/json',
  ],
]);

$body = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);

if ($status >= 400) {
  throw new RuntimeException('Wordly API request failed');
}
$data = json_decode($body, true, flags: JSON_THROW_ON_ERROR);

Dart / Flutter

Do not ship the Wordly key inside a Flutter application. The example belongs in a trusted Dart backend or server function.

final response = await http.get(
  Uri.parse('https://api.wordlyenglish.com/v1/account'),
  headers: {
    'Authorization': 'Bearer ${Platform.environment['WORDLY_API_KEY']}',
    'Accept': 'application/json',
  },
);

final body = jsonDecode(response.body) as Map<String, dynamic>;
if (response.statusCode >= 400) {
  throw Exception((body['error'] as Map)['code']);
}

Production checklist

  • Proxy Wordly requests through a trusted backend.
  • Set connection and response timeouts.
  • Handle 401, 402, 404, and 5xx separately.
  • Query GET /v1/account when your application needs the current balance.
  • Log endpoint, status, latency, and request_id without logging the API key.
  • Use separate keys per environment and rotate them periodically.
  • Cache stable vocabulary responses in your backend when appropriate.

Ready to make your first request?

Create an account, verify your email, and receive 50 free credits.

Create free account

Need integration help? Email [email protected].