Get a case study
GET/api/v1/case-studies/{slug}
- Since
- 1.1.0
- Auth
- Bearer key
- operationId
- getCaseStudy
One published case study with before and after images, content blocks and linked treatments. A thing moved to the trash in the clinic's panel answers 404 under its address; after a restore it answers again under the same address. Responses are private to the key: Cache-Control: private, max-age=60, so cache them on your side for up to a minute.
Request
Send the clinic's key in Authorization: Bearer (see API keys).
Path parameters
- slugstringrequired
Slug of the case study (lower-case letters, digits, hyphens).
curl "https://app.pozyskajpacjenta.pl/api/v1/case-studies/pelna-odbudowa-usmiechu" \
-H "Authorization: Bearer $PP_API_KEY"import { PozyskajPacjentaClient } from "@pozyskajpacjenta/sdk";
const client = new PozyskajPacjentaClient({
apiKey: process.env.PP_API_KEY ?? "",
baseUrl: "https://app.pozyskajpacjenta.pl",
});
const { caseStudy } = await client.getCaseStudy("pelna-odbudowa-usmiechu");<?php
$response = wp_remote_get(
'https://app.pozyskajpacjenta.pl/api/v1/case-studies/pelna-odbudowa-usmiechu',
array(
'headers' => array( 'Authorization' => 'Bearer ' . getenv( 'PP_API_KEY' ) ),
'timeout' => 10,
)
);
if ( is_wp_error( $response ) ) {
error_log( $response->get_error_message() );
return;
}
$status = wp_remote_retrieve_response_code( $response );
$data = json_decode( wp_remote_retrieve_body( $response ), true );Response
200The case study.
- caseStudyCaseStudyDetailrequired
The case study.
Fields (17)
- idstringrequired
Case study id.
- slugstringrequired
Slug from the case study's address.
- pathstringrequired
Path of the case study page.
- titlestringrequired
Title.
- summarystring | null
Short summary; null when empty.
- beforeMediaRef | null
Image before the treatment. Since 1.20.0: a patient's photo added with consent, only when the patient agreed to show it on the clinic's site, served from /api/case-study-photo/{id} (supports ?w= and ?f=, cached briefly). A case study added before 1.20.0 keeps its library image as before until the patient refuses or withdraws. Otherwise null.
Fields (8)
- urlstringrequired
Absolute address of the file.
- focalXinteger | null
Horizontal focal point in percent (0 to 100) to keep when cropping, e.g. as object-position.
- focalYinteger | null
Vertical focal point in percent (0 to 100).
- altstring | null
Alternative text; null when the clinic left it empty.
- widthintegersince 1.4.0
Width of the original in px (library files, when known), for width/height attributes without layout shift.
- heightintegersince 1.4.0
Height of the original in px.
- aiGeneratedbooleansince 1.4.0
The image was generated by AI: label it next to the image (e.g. in a caption).
- captionstringsince 1.4.0
Caption to show under the image.
- afterMediaRef | null
Image after the treatment. Since 1.20.0: a patient's photo added with consent, only when the patient agreed to show it on the clinic's site, served from /api/case-study-photo/{id} (supports ?w= and ?f=, cached briefly). A case study added before 1.20.0 keeps its library image as before until the patient refuses or withdraws. Otherwise null.
Fields as in MediaRef above.
- bodyBlocksBlock[]required
Content blocks of the case study.
Fields of each item (4)
- idstringrequired
Block id, stable within the page.
- typestringrequired
Block type with its version, e.g. hero.v1, faq.v1.
- propsobjectrequired
The block's fields; their shape depends on
type. - styleobjectsince 1.29.0
The section's frame, beside its content. Present on the blocks of a page.
Fields (1)
- tonestringsince 1.29.0
The surface the section stands on:
base(the page's ground),soft(a quiet step off it),contrast(the opposite polarity: a dark band on a light theme) orbrand(the theme's main colour as the ground). The clinic's site alternatesbaseandsoftdown the page unless the clinic chose a tone; derive a tone's colours from the theme tokens.One of
basesoftcontrastbrand
- servicesRelatedService[]required
Treatments linked to the case study (published ones only).
Fields of each item (5)
- idstringrequired
Treatment id.
- slugstringrequired
Treatment slug.
- pathstringrequired
Path of the treatment page.
- namestringrequired
Treatment name.
- priceFromLabelstring | null
Price label, e.g. od 290 zł; null when the clinic shows no price.
- publishedAtstring (date-time) | null
Publication date, ISO 8601; null when unknown.
- updatedAtstring (date-time)required
Last change, ISO 8601.
- resultsNotestring
Since 1.21.0: the fixed note to show with every case study ("Efekty zależą od indywidualnych cech pacjenta.").
- storyCaseStudyStory | null
Since 1.21.0: the four-part description; null for older case studies (their text is in bodyBlocks).
Fields (4)
- problemstringrequired
What the patient came with.
- treatmentstringrequired
What the clinic did.
- coursestringrequired
How the treatment went.
- effectstringrequired
The result.
- pairsCaseStudyPair[]
Since 1.21.0: every before and after pair; empty without the patient's consent.
- sessionsCountinteger | null
Since 1.21.0: the number of treatment sessions; null when not given.
- resultAfterDaysinteger | null
Since 1.21.0: how many days after the treatment the after photo was taken; null when not given.
- doctorSlugstring | null
Since 1.21.0: the specialist (GET /doctors/{slug}) when published; null otherwise.
A case study (body trimmed to one block)
{
"caseStudy": {
"id": "cs_odbudowa",
"slug": "pelna-odbudowa-usmiechu",
"path": "/realizacje/pelna-odbudowa-usmiechu",
"title": "Pełna odbudowa uśmiechu na implantach",
"summary": "Pacjent, 58 lat, po latach unikania dentysty: sześć implantów, korony pełnoceramiczne i nowy zgryz w cztery miesiące, bez jednego dnia bez zębów.",
"before": null,
"after": null,
"bodyBlocks": [
{
"id": "cs-odb-wyzwanie",
"type": "rich-text.v1",
"props": {
"variant": "narrow",
"heading": "Wyzwanie",
"body": "Pan Andrzej trafił do nas po kilkunastu latach przerwy w leczeniu: brakujące zęby boczne, starte zęby przednie i zgryz obniżony tak, że zmieniał rysy twarzy. Najbardziej bał się nie zabiegów, a tego, że na czas leczenia zostanie bez zębów."
}
}
],
"services": [],
"publishedAt": "2026-06-20T00:00:00.000Z",
"updatedAt": "2026-09-30T14:21:58.000Z",
"resultsNote": "Efekty zależą od indywidualnych cech pacjenta.",
"story": null,
"pairs": [],
"sessionsCount": null,
"resultAfterDays": null,
"doctorSlug": null
}
}Errors
| Status | When |
|---|---|
| 401 | No Authorization header |
| 401 | Unknown or rotated key |
| 404 | No published treatment with this slug |
| 429 | Over 120 requests in this minute |
Branch on the status and code, never on the Polish error text. All statuses in Errors.
{
"error": "missing Authorization: Bearer <klucz z panelu Ustawienia>"
}{
"error": "invalid key"
}{
"error": "nie znaleziono"
}{
"error": "przekroczono limit 120 zapytań/min"
}Rate limit
- 120 requests per minute per key, shared by every endpoint.
- Every response to a valid key carries
RateLimit-RemainingandRateLimit-Reset; see Rate limits.
SDK method
client.getCaseStudy(slug: string): Promise<{ caseStudy: CaseStudyDetail }>
The TypeScript tab above uses it. Install and errors: TypeScript SDK.