Türkçe · English
Percentile API
Percentiles and z-scores on your own site, using WHO, CDC and Neyzi references. The calculation is the same as the pediatrirutinleri.com percentile calculator.
Embedded form
No coding: add two lines to your page and the calculator opens on your site. No key is needed; the form works only on your approved domains.
API
For your own interface and server: send measurements from your server and receive JSON results. One measurement or up to 100 per request.
1. Application and key
- Sign in with your Pediatri Rutinleri account (your mobile app account works too; if you have none, register for free) and apply on the Percentile API service page (in Turkish): organisation, website, intended use; your server IP addresses for the API, your domains for the embedded form. The application is linked to your account and the result is sent to your account's email address.
- Every application is reviewed by an administrator and you are answered by email. Use is currently free within a daily quota.
- If the embedded form is approved, the embed code arrives by email.
- If the API is approved, you receive a one-time link (valid for 72 hours). The key is generated when you press “Show key” on that page and is shown only once. The key is never emailed and we do not store it in plain text. If you lose it, a new one is issued.
2. Embedded form
Add the code from the approval email to your page (SITE_ID is the identifier you were given):
<iframe src="https://pediatrirutinleri.com/api/widget/?site=SITE_ID"
title="Persentil hesaplayıcı" style="width:100%;min-height:720px;border:0"
loading="lazy" referrerpolicy="strict-origin"></iframe>
<script src="https://pediatrirutinleri.com/api/widget/gomme.js" async></script>
gomme.jssizes the frame to its content; without it themin-heightvalue is used.- Optional parameters:
&ref=cdc(reference selected by default:who,cdc,neyzi),&color=2f6f5f(button colour, without #). - The form opens only on the HTTPS domains given in your application. For a new domain (e.g. with
www.), write to us. - There is a per-minute limit per visitor and a daily limit for your site; we can raise it if you need more.
- Results come with growth charts for height, weight, head circumference and BMI.
- The form interface is currently in Turkish.
If your site uses a Content-Security-Policy (CSP)
If the form does not appear, your site's security policy is most likely blocking external frames. Add this to your CSP header:
frame-src … https://pediatrirutinleri.com
script-src … https://pediatrirutinleri.com (optional: only for automatic height)
Without script-src the form still works; only gomme.js is not loaded and the frame keeps the min-height from the code. If you cannot change your CSP, use the API with your own form.
3. API
POST https://pediatrirutinleri.com/api/v1/persentil.php
| Header | Value |
|---|---|
Authorization | Bearer prk_live_… (never in the URL) |
Content-Type | application/json |
User-Agent | Your application's name. The server protection may reject requests without a User-Agent. |
Request
{
"id": "meas-8812",
"ref": "who",
"sex": 1,
"bday": "2024-03-15",
"tday": "2026-10-01",
"height": 89.4,
"measure": "h",
"weight": 12.6,
"hc": 47.5,
"gaw": 34,
"gad": 2,
"mheight": 162,
"dheight": 178,
"lang": "en"
}
Batch: {"items": [ {…}, {…} ]} (up to 100 measurements).
| Field | Required | Description |
|---|---|---|
ref | yes | Reference: who, cdc, neyzi |
sex | yes | 1 = female, 2 = male |
bday + tday | one of | Birth date + measurement date, YYYY-MM-DD; both together |
agedays | or this | Chronological age in days (0–7305) |
height / weight / hc | at least one | Height cm (20–250) / weight kg (0.2–300) / head circumference cm (15–80) |
measure | no | How height was measured: l = recumbent (length), h = standing (height). If it differs from what the reference expects, height is adjusted (CDC 0.8 cm, WHO/Neyzi 0.7 cm). If omitted, no adjustment is made. |
gaw, gad | no | Preterm birth: gestational age in weeks 22–36 and days 0–6 (integers). Corrected age is used up to 24 months chronological age. |
mheight, dheight | no | Mother's and father's height, cm; given together they produce target height |
id | no | A short technical identifier to match your own record: up to 64 characters, letters, digits and _ . : -. Returned as is. |
lang | no | Language of error messages: tr (default) or en. If omitted, the Accept-Language header is used. Field names and codes are language-independent. |
graph | no | true: growth curves are included (single requests only, see below) |
Numbers may be JSON numbers (89.4) or strings with a decimal point ("89.4"). Unknown fields are ignored.
Response
{
"success": true,
"result": {
"id": "meas-8812", "ref": "who", "sex": 1,
"age": { "months": 29.3, "chrono": {"total_days": 930, "years": 2, "months": 6, "days": 16}, "corrected": null },
"preterm": { "applied": false, "reason": "over_24_months", "gaw": 34, "gad": 2, "corr_days": null, "pma_days": null },
"height": { "measured": 89.4, "used": 90.1,
"measure_adj": {"measure": "h", "expected": "l", "diff_cm": 0.7},
"z": 0.12, "p": 54.78, "height_age_m": 28.4, "ideal_weight": 12.9 },
"weight": { "value": 12.6, "z": -0.05, "p": 47.9, "rel_weight": 98 },
"hc": { "value": 47.5, "z": 0.3, "p": 61.2 },
"bmi": { "value": 15.52, "z": …, "p": … },
"wfh": { "z": …, "p": … },
"target": { "cm": 163.5, "low": 156.5, "high": 170.5, "z": 0.21 }
},
"request_id": "9f2c…"
}
| Field | Meaning |
|---|---|
age.months | Age used in the calculation, months (corrected if preterm) |
age.chrono / age.corrected | Chronological / corrected age: total days, years, months, days |
preterm | Preterm correction (null if gaw was not sent). reason: over_24_months (chronological age is over 24 months), invalid_gaw, invalid_gad. corr_days: days subtracted, pma_days: postmenstrual age in days |
height.measured / height.used | Height sent / height used after the measurement-method adjustment |
height.measure_adj | Measurement-method adjustment (null if none): method sent and method the reference expects (l/h), difference in cm |
z, p | Z-score and percentile |
height.height_age_m, height.ideal_weight | Height age (months) and ideal weight (kg) |
weight.rel_weight | Relative weight, % |
wfh | Weight for height |
target | Target height (cm) and its range; z against the 18-year reference |
- Only the sections for the measurements you sent are returned; BMI and weight for height need both height and weight.
- For age or height outside the reference range,
zandpare null (not clamped to the extreme value). - Weight for height: WHO 45–120 cm; CDC over 24 months, 77–121.5 cm. Not available for Neyzi.
- A batch response contains a
resultsarray; each item hasindex,successand eitherresultorerror(plusidwhen it failed). A failed measurement does not block the others and is not counted against the quota.
Growth curves (optional)
Send "graph": true in a single request and result.graphs is added: for each measurement sent that lies within the reference range (height, weight, hc, bmi), the P3, P10, P25, P50, P75, P90 and P97 curves and the child's point. You can draw your own chart from it. Batch requests return no curves.
"graphs": {
"height": {
"unit": "cm", "x_unit": "month", "x_range": [0, 23.984],
"centiles": [3, 10, 25, 50, 75, 90, 97],
"x": [0, 0.493, …], // age (months)
"p": { "3": [45.6, …], "50": [49.1, …], "97": [52.7, …], … },
"point": [13.142, 76.0] // [age used (months), value used]
}
}
The window follows the child's age: 0–24 months up to age 2, 0–60 months up to age 5, otherwise 60–240 months (as far as the reference table covers). Corrected age is used for preterm children and adjusted height after a measurement-method adjustment.
Example: PHP
$key = getenv('PR_PERCENTILE_API_KEY'); // never hard-code it
$ch = curl_init('https://pediatrirutinleri.com/api/v1/persentil.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_USERAGENT => 'ExampleClinic/1.0',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $key, 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'ref' => 'who', 'sex' => 2,
'bday' => '2025-01-10', 'tday' => '2026-10-01',
'height' => 82.0, 'weight' => 11.2, 'lang' => 'en',
]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
Example: Node.js (18+)
const res = await fetch('https://pediatrirutinleri.com/api/v1/persentil.php', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PR_PERCENTILE_API_KEY}`,
'Content-Type': 'application/json',
'User-Agent': 'ExampleClinic/1.0',
},
body: JSON.stringify({ ref: 'cdc', sex: 1, agedays: 1500, height: 101.2, weight: 15.8, lang: 'en' }),
});
const data = await res.json();
4. Proxy file for forms your visitors fill in
If your site's visitors enter the measurements, the browser must not call the API directly (the key would be visible in the page source and stolen). The flow should be:
Visitor's browser → your server (proxy file) → pediatrirutinleri.com API
Important: your proxy file is public. Without protection, anyone can call it in a loop and use up your daily quota. Take at least these three measures: accept requests only from your own page, limit each visitor, allow only single measurements. If your form is public, we also recommend a CAPTCHA.
Example proxy file (PHP with APCu; without APCu, keep the counter in a database or Redis):
<?php
// https://your-site.com/percentile.php
const SITE_ORIGIN = 'https://your-site.com';
const MINUTE_LIMIT = 20; // per visitor IP
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); exit; }
// 1) Only from your own page
if (($_SERVER['HTTP_ORIGIN'] ?? '') !== SITE_ORIGIN) { http_response_code(403); exit; }
// 2) Per-visitor limit per minute
$counter = 'prp_' . hash('sha256', $_SERVER['REMOTE_ADDR']);
apcu_add($counter, 0, 60);
if (apcu_inc($counter) > MINUTE_LIMIT) { http_response_code(429); exit; }
// 3) Single measurement and known fields only (batch "items" is not passed on)
$input = json_decode(file_get_contents('php://input', false, null, 0, 4096), true);
$allowed = ['ref', 'sex', 'bday', 'tday', 'agedays', 'height', 'weight', 'hc',
'measure', 'gaw', 'gad', 'mheight', 'dheight', 'lang'];
$item = is_array($input) ? array_intersect_key($input, array_flip($allowed)) : [];
// 4) Call the API from your server, key from an environment variable
$ch = curl_init('https://pediatrirutinleri.com/api/v1/persentil.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_USERAGENT => 'YourSite/1.0',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('PR_PERCENTILE_API_KEY'),
'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($item ?: new stdClass()),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($body === false || $status >= 500) {
http_response_code(502);
echo json_encode(['success' => false, 'error' => ['code' => 'server_error', 'message' => 'Calculation is unavailable right now.']]);
exit;
}
http_response_code($status);
echo $body; // API response as is
The JavaScript on your page calls this file with fetch('/percentile.php', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(item)}). If you prefer not to write code, use the embedded form.
5. Errors and limits
{ "success": false, "error": { "code": "invalid_input", "message": "…", "field": "height" }, "request_id": "…" }
code and field are language-independent; base your program on them. message is in Turkish or English according to lang.
| HTTP | code | What to do |
|---|---|---|
| 400 | invalid_input, invalid_body, too_many_items | Fix the input; field tells you which field. |
| 401 | unauthorized | Key missing, wrong or revoked. |
| 403 | ip_not_allowed, https_required | Call from an allowed IP, over HTTPS. |
| 405 / 413 / 415 | method_not_allowed / body_too_large / unsupported_media_type | POST only / body at most 64 KB / Content-Type: application/json |
| 429 | rate_limited, quota_exceeded | Respect the Retry-After header; the quota resets at midnight Istanbul time. |
| 5xx | server_error | Try again later. |
When the general per-IP limit is exceeded, the 429 body has the form {"success": false, "error": "…"}; act on the HTTP status.
Response headers: X-RateLimit-Limit, X-RateLimit-Remaining (requests per minute), X-Quota-Limit, X-Quota-Remaining (measurements per day), X-Request-Id (quote it when asking for support).
6. Security and personal data
- Do not send personal data. The calculation needs no name, ID number or file number. Measurements are not stored or logged; only daily request and measurement counts are kept.
- Keep the key on your server only (environment variable or configuration file). Never put it in browser code, a mobile app or a public repository.
- Have your key restricted to your server IP addresses; even if it leaks, it cannot be used elsewhere.
- If your key leaks, tell us immediately; we revoke it and issue a new one.
Results are for clinical decision support; diagnosis and treatment decisions belong to the physician.
Pediatri Rutinleri · Privacy (Turkish) · Terms of use (Turkish)