Starter
£0
Try the API free for 24 hours.
- 100 API requests
- 24-hour access
- Full documentation
- Basic support
- Redeem code required
API v1.0
Give your users answers about food banks, free meals, support services and local events through one REST endpoint that uses the familiar chat-completions format.
curl https://nyataai.co.uk/external_api.php \
-H "Content-Type: application/json" \
-H "X-API-Key: $NYATA_API_KEY" \
-d '{
"model": "ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP",
"messages": [{
"role": "user",
"content": "Where can I get a free meal today?"
}]
}'
{
"choices": [{
"message": {
"role": "assistant",
"content": "Several free meal services are open today..."
},
"finish_reason": "stop"
}]
}
Create an account, then buy a plan or redeem a free-trial code.
Get an API keyReady-to-run scripts for macOS, Linux, Windows, Python and Node.js, with nothing to install.
Paste your key into .env and run one command.
Start with a free trial, then choose the plan that fits. No hidden fees.
£0
Try the API free for 24 hours.
£10/month
For individual developers.
£50/month
For growing businesses.
Custom
For large-scale deployments.
You'll need to log in or create an account to buy an API key.
Local knowledge people can act on, behind an API that's easy to work with.
Answers about food banks, free meals, support services, events and community resources, from a model fine-tuned on local community information.
OpenAI-compatible requests and responses, so most chat-completion code needs only a new URL and key header.
Documented status codes, a Retry-After header on rate limits and a distinct quota_exceeded error, so your integration can fail gracefully.
Registered with the UK Information Commissioner's Office (ZC042900). Every request is authenticated with your key and encrypted over HTTPS.
Track your requests, remaining quota and reset date from your API dashboard.
The API points people to the right service. Bookings and payments stay with providers, so partners keep their own customer relationships.
Everything you need to integrate Nyata AI into your application.
The Nyata AI API gives your application the same local knowledge that powers the Nyata app. Send a question as a chat message and get back a reply in the familiar chat-completions format.
POST https://nyataai.co.uk/external_api.phpX-API-Key headerBuilt for discovery. The API recommends services and tells people where to go. It doesn't make bookings or take payments; those stay with the provider or happen in the Nyata app.
Make your first request in a few minutes. Each quickstart is a single file with nothing to install.
Ready-to-run quickstarts for Bash, PowerShell, Python and Node.js, plus a Postman collection, an OpenAPI spec and a settings template.
nyata-starter-kit/
├── README.md
├── .env.example
├── .gitignore
├── bash/quickstart.sh
├── windows/quickstart.ps1
├── python/quickstart.py
├── node/quickstart.mjs
├── postman/
│ └── nyata-api.postman_collection.json
└── openapi/
└── nyata-api.openapi.yaml
Copy it from your API dashboard. No key yet? Buy a plan or redeem a trial code.
Copy .env.example to .env, then paste your key after NYATA_API_KEY=.
# macOS / Linux
cp .env.example .env
# Windows
copy .env.example .env
Prefer environment variables? Set NYATA_API_KEY instead. It takes priority over .env.
Needs curl, which comes with macOS and most Linux distributions. Also works in WSL and Git Bash.
cd nyata-starter-kit
bash bash/quickstart.sh "Where can I find a food bank?"
#!/usr/bin/env bash
#
# Nyata AI API - quickstart for macOS, Linux, WSL and Git Bash
#
# Usage (from the starter-kit folder):
# bash bash/quickstart.sh "Where can I find a food bank?"
#
# Needs curl. If python3 or jq is installed, only the reply text is printed;
# otherwise you'll see the full JSON response.
#
# Your API key is read from the NYATA_API_KEY environment variable, or from a
# .env file in the current folder or the starter-kit folder.
set -euo pipefail
DEFAULT_API_URL="https://nyataai.co.uk/external_api.php"
DEFAULT_MODEL="ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP"
DASHBOARD_URL="https://nyataai.co.uk/api_dashboard.php"
MAX_RETRIES=4
KIT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# Read KEY=VALUE lines from a .env file. Variables that are already set win.
load_env() {
local file="$1" line key value
local pattern='^[[:space:]]*(export[[:space:]]+)?([A-Za-z_][A-Za-z0-9_]*)[[:space:]]*=[[:space:]]*(.*)$'
local double_quoted='^"(.*)"$'
local single_quoted="^'(.*)'\$"
[[ -f "$file" ]] || return 0
while IFS= read -r line || [[ -n "$line" ]]; do
line="${line%$'\r'}"
[[ "$line" =~ $pattern ]] || continue
key="${BASH_REMATCH[2]}"
value="${BASH_REMATCH[3]}"
value="${value%"${value##*[![:space:]]}"}"
if [[ "$value" =~ $double_quoted || "$value" =~ $single_quoted ]]; then
value="${BASH_REMATCH[1]}"
fi
if [[ -z "${!key:-}" ]]; then
export "$key=$value"
fi
done < "$file"
}
load_env "$PWD/.env"
load_env "$KIT_DIR/.env"
API_URL="${NYATA_API_URL:-$DEFAULT_API_URL}"
MODEL="${NYATA_MODEL:-$DEFAULT_MODEL}"
API_KEY="${NYATA_API_KEY:-}"
QUESTION="${*:-Where can I get a free meal today?}"
if [[ -z "$API_KEY" || "$API_KEY" == "your_api_key" ]]; then
echo "Add your API key first: copy .env.example to .env and paste your key," >&2
echo "or run: export NYATA_API_KEY=\"your_api_key\"" >&2
exit 1
fi
if ! command -v curl >/dev/null 2>&1; then
echo "This script needs curl. Install it, then try again." >&2
exit 1
fi
# Turn a string into a JSON string literal without extra tools.
json_string() {
local s
s="$(printf '%s' "$1" | tr -d '\001-\010\013\014\016-\037')"
s="${s//\\/\\\\}"
s="${s//\"/\\\"}"
s="${s//$'\n'/\\n}"
s="${s//$'\r'/\\r}"
s="${s//$'\t'/\\t}"
printf '"%s"' "$s"
}
BODY="{\"model\":$(json_string "$MODEL"),\"messages\":[{\"role\":\"user\",\"content\":$(json_string "$QUESTION")}],\"max_tokens\":300,\"temperature\":0.7}"
RESPONSE_FILE="$(mktemp)"
HEADERS_FILE="$(mktemp)"
trap 'rm -f "$RESPONSE_FILE" "$HEADERS_FILE"' EXIT
attempt=0
while true; do
if ! status="$(curl -sS "$API_URL" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-A "nyata-starter-kit/1.0 (bash)" \
--max-time 30 \
--data-binary "$BODY" \
-D "$HEADERS_FILE" -o "$RESPONSE_FILE" -w '%{http_code}')"; then
echo "Network error: could not reach $API_URL" >&2
exit 1
fi
# Retry rate limits (429) and server errors (5xx) with backoff.
if [[ "$status" == "429" || "$status" == 5* ]] && (( attempt < MAX_RETRIES )); then
delay="$(awk 'tolower($1) == "retry-after:" { gsub(/\r/, "", $2); print $2 }' "$HEADERS_FILE" | tail -n 1)"
if ! [[ "$delay" =~ ^[0-9]+$ ]]; then
delay=$(( 1 << attempt ))
fi
if (( delay > 60 )); then
delay=60
fi
echo "HTTP $status - retrying in ${delay}s..." >&2
sleep "$delay"
attempt=$(( attempt + 1 ))
continue
fi
break
done
if [[ "$status" == "200" ]]; then
if command -v python3 >/dev/null 2>&1 &&
PYTHONIOENCODING=utf-8 python3 -c 'import json, sys; print(json.load(sys.stdin)["choices"][0]["message"]["content"])' < "$RESPONSE_FILE" 2>/dev/null; then
exit 0
fi
if command -v jq >/dev/null 2>&1 && jq -er '.choices[0].message.content' < "$RESPONSE_FILE" 2>/dev/null; then
exit 0
fi
cat "$RESPONSE_FILE"
echo
exit 0
fi
case "$status" in
400) message="Bad request - check the model name and message format." ;;
401) message="Invalid or missing API key - check NYATA_API_KEY." ;;
403)
if grep -q "quota_exceeded" "$RESPONSE_FILE"; then
message="Monthly quota used up - check $DASHBOARD_URL or upgrade your plan."
else
message="This API key doesn't have access to the API."
fi
;;
429) message="Too many requests - slow down and try again shortly." ;;
5??) message="Nyata AI had a problem handling the request - try again in a moment." ;;
*) message="Unexpected response." ;;
esac
echo "Error $status: $message" >&2
if [[ -s "$RESPONSE_FILE" ]]; then
echo "Response: $(head -c 500 "$RESPONSE_FILE")" >&2
fi
exit 1
Works in Windows PowerShell 5.1, which comes with Windows 10 and 11, and in PowerShell 7. The -ExecutionPolicy Bypass flag applies to this one run only.
cd nyata-starter-kit
powershell -ExecutionPolicy Bypass -File .\windows\quickstart.ps1 "Where can I find a food bank?"
<#
.SYNOPSIS
Nyata AI API - quickstart for Windows PowerShell 5.1 and PowerShell 7+.
.DESCRIPTION
Sends one question to the Nyata AI API and prints the reply.
Your API key is read from the NYATA_API_KEY environment variable, or from
a .env file in the current folder or the starter-kit folder.
.EXAMPLE
powershell -ExecutionPolicy Bypass -File .\windows\quickstart.ps1 "Where can I find a food bank?"
#>
param(
[Parameter(Position = 0, ValueFromRemainingArguments = $true)]
[string[]]$Question
)
$ErrorActionPreference = "Stop"
$DefaultApiUrl = "https://nyataai.co.uk/external_api.php"
$DefaultModel = "ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP"
$DashboardUrl = "https://nyataai.co.uk/api_dashboard.php"
$MaxRetries = 4
# Windows PowerShell 5.1 needs TLS 1.2 switched on explicitly.
try {
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
} catch { }
# Show characters such as the pound sign correctly in the console.
try { [Console]::OutputEncoding = [Text.Encoding]::UTF8 } catch { }
function Write-Problem {
param([string]$Message)
[Console]::Error.WriteLine($Message)
}
# Read KEY=VALUE lines from a .env file. Variables that are already set win.
function Import-DotEnv {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { return }
foreach ($line in Get-Content -LiteralPath $Path -Encoding UTF8) {
if ($line -match '^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$') {
$key = $Matches[1]
$value = $Matches[2] -replace '^([''"])(.*)\1$', '$2'
if (-not [Environment]::GetEnvironmentVariable($key)) {
[Environment]::SetEnvironmentVariable($key, $value)
}
}
}
}
function Get-ErrorBody {
param($ErrorRecord)
if ($ErrorRecord.ErrorDetails -and $ErrorRecord.ErrorDetails.Message) {
return $ErrorRecord.ErrorDetails.Message
}
try {
# Windows PowerShell 5.1 keeps the body on the response stream.
$stream = $ErrorRecord.Exception.Response.GetResponseStream()
if ($stream.CanSeek) { $stream.Position = 0 }
return (New-Object IO.StreamReader($stream, [Text.Encoding]::UTF8)).ReadToEnd()
} catch {
return ""
}
}
function Get-RetryDelay {
param($Response, [int]$Attempt)
$delay = [Math]::Min([Math]::Pow(2, $Attempt), 60)
try {
$value = $null
if ($Response.Headers -is [System.Net.WebHeaderCollection]) {
$value = $Response.Headers["Retry-After"]
} elseif ($Response.Headers.RetryAfter -and $null -ne $Response.Headers.RetryAfter.Delta) {
$value = [int]$Response.Headers.RetryAfter.Delta.TotalSeconds
}
if ("$value" -match '^\d+$') { $delay = [Math]::Min([int]"$value", 60) }
} catch { }
return [int]$delay
}
$kitRoot = Split-Path -Parent $PSScriptRoot
Import-DotEnv (Join-Path (Get-Location).ProviderPath ".env")
Import-DotEnv (Join-Path $kitRoot ".env")
$apiKey = "$env:NYATA_API_KEY".Trim()
$apiUrl = if ($env:NYATA_API_URL) { $env:NYATA_API_URL } else { $DefaultApiUrl }
$model = if ($env:NYATA_MODEL) { $env:NYATA_MODEL } else { $DefaultModel }
$text = ($Question -join " ").Trim()
if (-not $text) { $text = "Where can I get a free meal today?" }
if (-not $apiKey -or $apiKey -eq "your_api_key") {
Write-Problem "Add your API key first: copy .env.example to .env and paste your key,"
Write-Problem 'or run: $env:NYATA_API_KEY = "your_api_key"'
exit 1
}
$payload = @{
model = $model
messages = @(@{ role = "user"; content = $text })
max_tokens = 300
temperature = 0.7
} | ConvertTo-Json -Depth 5 -Compress
$requestArgs = @{
Uri = $apiUrl
Method = "Post"
Headers = @{ "X-API-Key" = $apiKey }
ContentType = "application/json; charset=utf-8"
Body = [Text.Encoding]::UTF8.GetBytes($payload)
UserAgent = "nyata-starter-kit/1.0 (powershell)"
TimeoutSec = 30
UseBasicParsing = $true
}
for ($attempt = 0; ; $attempt++) {
$failure = $null
try {
$response = Invoke-WebRequest @requestArgs
} catch {
$failure = $_
}
if (-not $failure) { break }
$errorResponse = $failure.Exception.Response
if (-not $errorResponse) {
Write-Problem "Network error: could not reach $apiUrl ($($failure.Exception.Message))"
exit 1
}
$status = [int]$errorResponse.StatusCode
$detail = Get-ErrorBody $failure
# Retry rate limits (429) and server errors (5xx) with backoff.
if (($status -eq 429 -or $status -ge 500) -and $attempt -lt $MaxRetries) {
$delay = Get-RetryDelay $errorResponse $attempt
Write-Problem "HTTP $status - retrying in ${delay}s..."
Start-Sleep -Seconds $delay
continue
}
$message = switch ($status) {
400 { "Bad request - check the model name and message format." }
401 { "Invalid or missing API key - check NYATA_API_KEY." }
403 {
if ($detail -match "quota_exceeded") { "Monthly quota used up - check $DashboardUrl or upgrade your plan." }
else { "This API key doesn't have access to the API." }
}
429 { "Too many requests - slow down and try again shortly." }
default {
if ($status -ge 500) { "Nyata AI had a problem handling the request - try again in a moment." }
else { "Unexpected response." }
}
}
Write-Problem "Error ${status}: $message"
if ($detail) { Write-Problem "Response: $($detail.Substring(0, [Math]::Min(500, $detail.Length)))" }
exit 1
}
# Decode as UTF-8 explicitly so characters such as the pound sign survive.
$json = [Text.Encoding]::UTF8.GetString($response.RawContentStream.ToArray())
$reply = $null
try { $reply = ($json | ConvertFrom-Json).choices[0].message.content } catch { }
if ($reply -is [string]) {
Write-Output $reply
exit 0
}
Write-Problem "Unexpected response: $json"
exit 1
Needs Python 3.8 or newer and uses only the standard library. On Windows, type py instead of python3.
cd nyata-starter-kit
python3 python/quickstart.py "Where can I find a food bank?"
#!/usr/bin/env python3
"""Nyata AI API - Python quickstart (standard library only, Python 3.8+).
Usage (from the starter-kit folder):
python3 python/quickstart.py "Where can I find a food bank?"
Your API key is read from the NYATA_API_KEY environment variable, or from a
.env file in the current folder or the starter-kit folder.
To call the API from your own code, copy the ask() function into your project
or import it: from quickstart import ask
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request
from pathlib import Path
DEFAULT_API_URL = "https://nyataai.co.uk/external_api.php"
DEFAULT_MODEL = "ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP"
DASHBOARD_URL = "https://nyataai.co.uk/api_dashboard.php"
MESSAGES = {
400: "Bad request - check the model name and message format.",
401: "Invalid or missing API key - check NYATA_API_KEY.",
403: "This API key doesn't have access to the API.",
429: "Too many requests - slow down and try again shortly.",
}
class NyataError(Exception):
"""An API error that retrying won't fix. Has .status and .body."""
def __init__(self, status, body):
self.status = status
self.body = body
if status == 403 and "quota_exceeded" in body:
message = "Monthly quota used up - check %s or upgrade your plan." % DASHBOARD_URL
elif status >= 500:
message = "Nyata AI had a problem handling the request - try again in a moment."
else:
message = MESSAGES.get(status, "Unexpected response.")
super().__init__("Error %s: %s" % (status, message))
def ask(question, api_key, api_url=DEFAULT_API_URL, model=DEFAULT_MODEL,
max_tokens=300, temperature=0.7, max_retries=4):
"""Send one question to Nyata AI and return the reply text.
Retries rate limits (429) and server errors (5xx), honouring Retry-After.
Raises NyataError for other API errors.
"""
payload = json.dumps({
"model": model,
"messages": [{"role": "user", "content": question}],
"max_tokens": max_tokens,
"temperature": temperature,
}).encode("utf-8")
headers = {
"Content-Type": "application/json",
"X-API-Key": api_key,
"User-Agent": "nyata-starter-kit/1.0 (python)",
}
for attempt in range(max_retries + 1):
request = urllib.request.Request(api_url, data=payload, headers=headers, method="POST")
try:
with urllib.request.urlopen(request, timeout=30) as response:
status = response.status
raw = response.read().decode("utf-8", "replace")
except urllib.error.HTTPError as error:
body = error.read().decode("utf-8", "replace")
if (error.code == 429 or error.code >= 500) and attempt < max_retries:
delay = _retry_delay(error.headers.get("Retry-After"), attempt)
print("HTTP %s - retrying in %ss..." % (error.code, delay), file=sys.stderr)
time.sleep(delay)
continue
raise NyataError(error.code, body) from None
try:
return json.loads(raw)["choices"][0]["message"]["content"]
except (ValueError, KeyError, IndexError, TypeError):
raise NyataError(status, raw) from None
def _retry_delay(retry_after, attempt):
if retry_after and retry_after.strip().isdigit():
return min(int(retry_after.strip()), 60)
return min(2 ** attempt, 60)
def load_env():
"""Read KEY=VALUE lines from .env files. Variables already set win."""
kit_root = Path(__file__).resolve().parent.parent
for path in (Path.cwd() / ".env", kit_root / ".env"):
if not path.is_file():
continue
for line in path.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
key = key.strip()
if key.startswith("export "):
key = key[len("export "):].strip()
value = value.strip()
if len(value) >= 2 and value[0] == value[-1] and value[0] in "\"'":
value = value[1:-1]
if key:
os.environ.setdefault(key, value)
def main():
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(errors="replace")
load_env()
api_key = os.environ.get("NYATA_API_KEY", "").strip()
if not api_key or api_key == "your_api_key":
sys.exit("Add your API key first: copy .env.example to .env and paste your key,\n"
"or set the NYATA_API_KEY environment variable.")
question = " ".join(sys.argv[1:]).strip() or "Where can I get a free meal today?"
api_url = os.environ.get("NYATA_API_URL") or DEFAULT_API_URL
try:
reply = ask(question, api_key, api_url=api_url,
model=os.environ.get("NYATA_MODEL") or DEFAULT_MODEL)
except NyataError as error:
print(error, file=sys.stderr)
if error.body:
print("Response: %s" % error.body[:500], file=sys.stderr)
sys.exit(1)
except OSError as error:
reason = str(getattr(error, "reason", error))
print("Network error: could not reach %s (%s)" % (api_url, reason), file=sys.stderr)
if "CERTIFICATE_VERIFY_FAILED" in reason:
print("On macOS, run 'Install Certificates.command' from your Python folder "
"in Applications, then try again.", file=sys.stderr)
sys.exit(1)
print(reply)
if __name__ == "__main__":
main()
Needs Node.js 18 or newer. There's no npm install step.
cd nyata-starter-kit
node node/quickstart.mjs "Where can I find a food bank?"
#!/usr/bin/env node
// Nyata AI API - Node.js quickstart (Node.js 18+, no dependencies)
//
// Usage (from the starter-kit folder):
// node node/quickstart.mjs "Where can I find a food bank?"
//
// Your API key is read from the NYATA_API_KEY environment variable, or from a
// .env file in the current folder or the starter-kit folder.
//
// To call the API from your own code, copy ask() into your project or import it:
// import { ask } from './quickstart.mjs';
// Keep API calls on your server - never ship your API key in browser code.
import { existsSync, readFileSync } from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const DEFAULT_API_URL = 'https://nyataai.co.uk/external_api.php';
const DEFAULT_MODEL = 'ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP';
const DASHBOARD_URL = 'https://nyataai.co.uk/api_dashboard.php';
const MESSAGES = {
400: 'Bad request - check the model name and message format.',
401: 'Invalid or missing API key - check NYATA_API_KEY.',
403: "This API key doesn't have access to the API.",
429: 'Too many requests - slow down and try again shortly.',
};
// An API error that retrying won't fix. Has .status and .body.
export class NyataError extends Error {
constructor(status, body) {
let message = MESSAGES[status] ?? 'Unexpected response.';
if (status === 403 && body.includes('quota_exceeded')) {
message = `Monthly quota used up - check ${DASHBOARD_URL} or upgrade your plan.`;
} else if (status >= 500) {
message = 'Nyata AI had a problem handling the request - try again in a moment.';
}
super(`Error ${status}: ${message}`);
this.name = 'NyataError';
this.status = status;
this.body = body;
}
}
// Send one question to Nyata AI and return the reply text.
// Retries rate limits (429) and server errors (5xx), honouring Retry-After.
export async function ask(question, {
apiKey,
apiUrl = DEFAULT_API_URL,
model = DEFAULT_MODEL,
maxTokens = 300,
temperature = 0.7,
maxRetries = 4,
} = {}) {
const body = JSON.stringify({
model,
messages: [{ role: 'user', content: question }],
max_tokens: maxTokens,
temperature,
});
for (let attempt = 0; ; attempt += 1) {
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
'User-Agent': 'nyata-starter-kit/1.0 (node)',
},
body,
signal: AbortSignal.timeout(30000),
});
const text = await response.text();
if (response.ok) {
let reply;
try {
reply = JSON.parse(text).choices[0].message.content;
} catch {
// Handled below.
}
if (typeof reply === 'string') return reply;
throw new NyataError(response.status, text);
}
const retryable = response.status === 429 || response.status >= 500;
if (retryable && attempt < maxRetries) {
const delay = retryDelay(response.headers.get('retry-after'), attempt);
console.error(`HTTP ${response.status} - retrying in ${delay}s...`);
await new Promise((done) => setTimeout(done, delay * 1000));
continue;
}
throw new NyataError(response.status, text);
}
}
function retryDelay(retryAfter, attempt) {
const value = (retryAfter ?? '').trim();
const seconds = /^\d+$/.test(value) ? Number(value) : 2 ** attempt;
return Math.min(seconds, 60);
}
// Read KEY=VALUE lines from .env files. Variables that are already set win.
function loadEnv() {
const kitRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
for (const file of [join(process.cwd(), '.env'), join(kitRoot, '.env')]) {
if (!existsSync(file)) continue;
for (const line of readFileSync(file, 'utf8').split(/\r?\n/)) {
const match = line.match(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/);
if (!match) continue;
const [, key, rawValue] = match;
if (process.env[key] === undefined) {
process.env[key] = rawValue.replace(/^(['"])(.*)\1$/, '$2');
}
}
}
}
async function main() {
if (typeof fetch !== 'function') {
console.error('This script needs Node.js 18 or newer.');
process.exit(1);
}
loadEnv();
const apiKey = (process.env.NYATA_API_KEY ?? '').trim();
if (!apiKey || apiKey === 'your_api_key') {
console.error('Add your API key first: copy .env.example to .env and paste your key,');
console.error('or set the NYATA_API_KEY environment variable.');
process.exit(1);
}
const question = process.argv.slice(2).join(' ').trim() || 'Where can I get a free meal today?';
const apiUrl = process.env.NYATA_API_URL || DEFAULT_API_URL;
try {
const reply = await ask(question, {
apiKey,
apiUrl,
model: process.env.NYATA_MODEL || DEFAULT_MODEL,
});
console.log(reply);
} catch (error) {
if (error instanceof NyataError) {
console.error(error.message);
if (error.body) console.error(`Response: ${error.body.slice(0, 500)}`);
} else {
const reason = error.cause?.code ?? error.message;
console.error(`Network error: could not reach ${apiUrl} (${reason})`);
}
process.exit(1);
}
}
// Run main() only when this file is executed directly, not when imported.
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
await main();
}
The reply is printed in your terminal. If something goes wrong, the script explains the error and what to do about it.
Every request needs your API key in the X-API-Key header.
X-API-Key: your_api_keyFind your key on your API dashboard. New to Nyata? Create an account, then buy a plan or redeem a free-trial code. The examples on this page read your key from the NYATA_API_KEY environment variable.
Keep your key secret. Call the API from your server, never from browser or mobile-app code, and keep keys out of version control. The starter kit's .gitignore already excludes .env. If a key is exposed, email support@nyataai.co.uk straight away.
All requests go to one endpoint:
https://nyataai.co.uk/external_api.php
| Header | Value |
|---|---|
Content-Type | application/json |
X-API-Key | Your API key |
Always use HTTPS, and send the request body as JSON.
Send a JSON body with these parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Required | Model identifier: ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP |
messages | array | Required | The conversation so far, as message objects (see below). |
max_tokens | integer | Optional | Maximum length of the reply, in tokens. Default: 1000. |
temperature | number | Optional | From 0 to 1. Lower values give more focused replies. Default: 0.7. |
Send the model string exactly as shown. It's matched character for character, so don't shorten or change it.
| Field | Type | Description |
|---|---|---|
role | string | user for the person's question; assistant for earlier replies you include as context. |
content | string | The message text. |
{
"model": "ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP",
"messages": [
{ "role": "user", "content": "Where can I find a food bank?" }
],
"max_tokens": 300,
"temperature": 0.7
}
A successful request returns 200 and an OpenAI-compatible JSON object:
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1733500000,
"model": "ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "There are several food banks you can use this week..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 25,
"completion_tokens": 150,
"total_tokens": 175
}
}
| Field | Description |
|---|---|
choices[0].message.content | The reply text. This is usually the only field you need. |
choices[0].finish_reason | Why the reply ended. stop means it finished normally. |
usage | Tokens used by the request: prompt_tokens, completion_tokens and total_tokens. |
id, created, model | The completion's identifier, when it was created (Unix time) and the model that produced it. |
Any HTTP client works. Each example reads your key from the NYATA_API_KEY environment variable.
curl https://nyataai.co.uk/external_api.php \
-H "Content-Type: application/json" \
-H "X-API-Key: $NYATA_API_KEY" \
-d '{
"model": "ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP",
"messages": [{ "role": "user", "content": "Where can I find a food bank?" }],
"max_tokens": 300
}'
// Node.js 18+, on your server. Never expose your API key in browser code.
const response = await fetch('https://nyataai.co.uk/external_api.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.NYATA_API_KEY,
},
body: JSON.stringify({
model: 'ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP',
messages: [{ role: 'user', content: 'Where can I find a food bank?' }],
max_tokens: 300,
}),
});
if (!response.ok) {
throw new Error(`Nyata API error ${response.status}: ${await response.text()}`);
}
const data = await response.json();
console.log(data.choices[0].message.content);
# pip install requests
import os
import requests
response = requests.post(
"https://nyataai.co.uk/external_api.php",
headers={"X-API-Key": os.environ["NYATA_API_KEY"]},
json={
"model": "ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP",
"messages": [{"role": "user", "content": "Where can I find a food bank?"}],
"max_tokens": 300,
},
timeout=30,
)
response.raise_for_status()
print(response.json()["choices"][0]["message"]["content"])
<?php
$ch = curl_init('https://nyataai.co.uk/external_api.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . getenv('NYATA_API_KEY'),
],
CURLOPT_POSTFIELDS => json_encode([
'model' => 'ft:gpt-4.1-mini-2025-04-14:nyata:bristol:ChciyaQP',
'messages' => [['role' => 'user', 'content' => 'Where can I find a food bank?']],
'max_tokens' => 300,
]),
]);
$body = curl_exec($ch);
if ($body === false) {
throw new RuntimeException('Could not reach the Nyata API: ' . curl_error($ch));
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status !== 200) {
throw new RuntimeException("Nyata API error $status: $body");
}
$data = json_decode($body, true);
echo $data['choices'][0]['message']['content'], PHP_EOL;
Official Python and JavaScript SDKs are in development. Until they're released, the starter kit's ask() helpers give you retries and clear errors with no dependencies.
The API uses standard HTTP status codes.
| Status | Meaning | What to do |
|---|---|---|
200 OK | Success. | Read choices[0].message.content. |
400 Bad Request | Invalid parameters. | Check the model string and message format. Retrying the same request won't help. |
401 Unauthorized | Invalid or missing API key. | Check the X-API-Key header. |
403 Forbidden | The key doesn't have access, or your plan's monthly quota is used up (quota_exceeded). | Don't retry. Check your dashboard, upgrade, or wait for your quota to reset. |
429 Too Many Requests | You're sending requests faster than your plan allows. | Wait for the number of seconds in the Retry-After header, then retry. |
500 Server Error | Something went wrong on our side. | Retry with exponential backoff. |
403 or 429? A 403 with quota_exceeded means you've used your plan's full monthly allowance: upgrade, or wait for your billing cycle to reset. A 429 means you're within your quota but sending requests too quickly: slow down and retry.
Every plan has a monthly request allowance, shown under Pricing, plus a short-term rate limit that keeps the API responsive for everyone.
429, wait for the number of seconds in the Retry-After header, then retry.429 or 5xx responses, back off exponentially: 1s, 2s, 4s, 8s.403 with quota_exceeded, stop retrying and check your dashboard for your remaining quota and reset date.The starter-kit scripts already follow this strategy, so you can copy their ask() helpers into your own project.
The current API version is v1.0. The model string is versioned separately from the API itself.
We'll give advance notice before any breaking change to the endpoint, the request format or the model identifier, so you have time to update your integration.
The starter kit contains everything below. You can also download each file on its own.
apiKey variable, then send.
Email support@nyataai.co.uk with the time of the request, the endpoint, the status code and the response body. Never include your full API key.
Answers to common questions are in the Help Center and FAQs.