Referentie
Catalogus
De agenda: openbare gegevens, voor elk token gelijk. Vraagt read.
The agenda: public data, the same for every token.
De beschrijvingen van de endpoints komen uit de specificatie en zijn in het Engels.
GET/events
List events
Every approved event in the agenda for NL and BE, soonest first. Defaults to today onwards. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
city optioneel | query | string | - | Only events in this city. Matched case-insensitively against the venue's city. |
genre optioneel | query | string | - | Only events carrying this genre, exactly as /v1/genres spells it. |
from optioneel | query | string (date) | - | First date, yyyy-mm-dd. Defaults to today in Europe/Amsterdam. |
to optioneel | query | string (date) | - | Last date, yyyy-mm-dd, inclusive. |
venue_id optioneel | query | string | - | Only events in this venue. |
artist_id optioneel | query | string | - | Only events this artist is billed on. |
organisation_id optioneel | query | string | - | Only events from this organisation. |
q optioneel | query | string | - | Free text over the title and the venue name. |
has_tickets optioneel | query | boolean | - | True: only events you can buy a ticket for right now. False: only events you cannot. |
max_price optioneel | query | number>= 0 | - | Only events whose cheapest ticket is at most this, in euros. 0 means free entry only. |
min_price optioneel | query | number>= 0 | - | Only events whose cheapest ticket is at least this, in euros. Free entry and an unknown price never pass a floor above 0. |
lat optioneel | query | number-90..90 | - | Latitude of the centre for a radius search, with lng. Only venues with coordinates can match. |
lng optioneel | query | number-180..180 | - | Longitude of the centre for a radius search, with lat. |
radius_km optioneel | query | integer1..200 | - | How far from lat,lng a venue may be, in kilometres. Needs lat and lng. Defaults to 25. |
limit optioneel | query | integer1..100 | 25 | Items per page, 1 to 100. |
cursor optioneel | query | string | - | Opaque cursor from meta.next_cursor of the previous page. Do not build one yourself. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/events?city=Amsterdam&limit=25" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/events?city=Amsterdam&limit=25", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/events?city=Amsterdam&limit=25",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": [
{
"id": "oost-sat",
"slug": "oost-hard-techno-night",
"title": "OOST: Hard Techno Night",
"date": "2026-10-03",
"end_date": null,
"start": "23:00",
"end": "06:00",
"timezone": "Europe/Amsterdam",
"status": "approved",
"cancelled": false,
"cancel_reason": null,
"postponed_to": null,
"genres": [
"Hard techno",
"Techno"
],
"price": 18,
"price_max": 25,
"currency": "EUR",
"age": 18,
"ticket_url": null,
"artwork_url": "https://partyppl.nl/media/imports/oost/oost-sat.jpg",
"venue": {
"id": "oost",
"name": "OOST",
"city": "Amsterdam",
"address": "Zeeburgerpad 1, 1018 AJ Amsterdam",
"lat": 52.3701,
"lng": 4.9412
},
"organisation": {
"id": "oost-collective",
"name": "OOST Collective"
},
"url": "https://partyppl.nl/e/oost-hard-techno-night",
"updated_at": 1758499200
}
],
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"count": 1,
"limit": 25,
"next_cursor": null,
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200List events400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/events/{id}
Get one event
One event by its id or by its slug, with the bill, the set times when there are any and the festival maps. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
id verplicht | path | string | - | The id of the resource. Events also accept their slug. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/events/oost-sat" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/events/oost-sat", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/events/oost-sat",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": {
"id": "oost-sat",
"slug": "oost-hard-techno-night",
"title": "OOST: Hard Techno Night",
"date": "2026-10-03",
"end_date": null,
"start": "23:00",
"end": "06:00",
"timezone": "Europe/Amsterdam",
"status": "approved",
"cancelled": false,
"cancel_reason": null,
"postponed_to": null,
"genres": [
"Hard techno",
"Techno"
],
"price": 18,
"price_max": 25,
"currency": "EUR",
"age": 18,
"ticket_url": null,
"artwork_url": "https://partyppl.nl/media/imports/oost/oost-sat.jpg",
"venue": {
"id": "oost",
"name": "OOST",
"city": "Amsterdam",
"address": "Zeeburgerpad 1, 1018 AJ Amsterdam",
"lat": 52.3701,
"lng": 4.9412
},
"organisation": {
"id": "oost-collective",
"name": "OOST Collective"
},
"url": "https://partyppl.nl/e/oost-hard-techno-night",
"updated_at": 1758499200,
"description": "Twee vloeren, hard techno tot zes uur.",
"lineup": [
{
"id": "amelie-lens",
"name": "Amelie Lens",
"order": 0
},
{
"id": "vril",
"name": "Vril",
"order": 1
}
],
"timetable": {
"Main": [
[
"23:00",
"Vril"
],
[
"01:00",
"Amelie Lens"
]
]
},
"maps": [
{
"label": "Plattegrond",
"image_url": "https://partyppl.nl/media/imports/oost/plattegrond.png",
"source": null
}
],
"rules": [
"18+, legitimatie verplicht",
"Geen fotos op de dansvloer"
],
"dress": null,
"source": "partyflock",
"source_url": "https://partyflock.nl/party/498065"
},
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200Get one event400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.404No such resource.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/events/{id}/token-prices
What a token costs at this festival
Dutch and Belgian festivals sell drinks in munten, and what that costs is worked out here from what visitors reported: euros per token at the till and in advance, tokens per drink and therefore the price of a beer, whether unspent tokens are refunded, what the previous edition cost, and how it sits against the rest of the season. Nothing in the answer was checked by us. verified is always false and reports and last_report_at are always there, so anything you build with it can say who said so and when. 404 for an event that is not a festival. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
id verplicht | path | string | - | The id of the resource. Events also accept their slug. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/events/oost-sat/token-prices" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/events/oost-sat/token-prices", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/events/oost-sat/token-prices",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": {
"event_id": "awakenings-2027",
"festival_key": "awakenings",
"season": 2027,
"verified": false,
"reports": 11,
"last_report_at": 1782000000,
"confidence": "good",
"token_price": 3.6,
"token_price_channel": "onsite",
"presale": 3.4,
"onsite": 3.6,
"saving": 0.2,
"drink_tokens": 2,
"drink_price": 7.2,
"refund": "no",
"outliers": 1,
"example": {
"paid": 18,
"tokens": 5
},
"previous_edition": {
"event_id": "awakenings-2026",
"title": "Awakenings Festival 2026",
"date": "2026-07-04",
"season": 2026,
"token_price": 3.4,
"drink_price": 6.8,
"reports": 8
},
"season_compare": {
"season": 2027,
"median": 3.4,
"festivals": 14,
"diff": 0.2
},
"url": "https://partyppl.nl/e/awakenings-festival-2027#munten"
},
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200What a token costs at this festival400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.404No such resource.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/events/{id}/token-reports
The token reports behind that price
The individual reports the price above is built from, newest first, so the working can be checked. Anonymous by design: each report carries what was paid and how close the reporter stood to the night (tier, which is what their weight is built from), and never who they are. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
id verplicht | path | string | - | The id of the resource. Events also accept their slug. |
limit optioneel | query | integer1..100 | 25 | Items per page, 1 to 100. |
cursor optioneel | query | string | - | Opaque cursor from meta.next_cursor of the previous page. Do not build one yourself. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/events/oost-sat/token-reports?limit=25" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/events/oost-sat/token-reports?limit=25", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/events/oost-sat/token-reports?limit=25",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": [
{
"id": "tp_8cQ2fR",
"paid": 18,
"tokens": 5,
"token_price": 3.6,
"drink_tokens": 2,
"channel": "onsite",
"refund": "no",
"tier": "ticket",
"weight": 5,
"created_at": 1782000000
}
],
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"count": 1,
"limit": 25,
"next_cursor": null,
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200The token reports behind that price400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.404No such resource.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/venues
List venues
Clubs, concert halls and festival sites, by name. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
city optioneel | query | string | - | Only venues in this city. |
q optioneel | query | string | - | Free text over the name. |
with_events optioneel | query | boolean | - | True: only venues with at least one event from today on. |
limit optioneel | query | integer1..100 | 25 | Items per page, 1 to 100. |
cursor optioneel | query | string | - | Opaque cursor from meta.next_cursor of the previous page. Do not build one yourself. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/venues?city=Rotterdam&limit=25" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/venues?city=Rotterdam&limit=25", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/venues?city=Rotterdam&limit=25",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": [
{
"id": "oost",
"name": "OOST",
"city": "Amsterdam",
"area": "Oost",
"address": "Zeeburgerpad 1, 1018 AJ Amsterdam",
"lat": 52.3701,
"lng": 4.9412,
"website": "https://clubooost.nl",
"tags": [
"club",
"techno"
],
"rating": 4.4,
"reviews_count": 128,
"image_url": "https://partyppl.nl/media/venues/oost.jpg",
"url": "https://partyppl.nl/locatie/oost"
}
],
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"count": 1,
"limit": 25,
"next_cursor": null,
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200List venues400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/venues/{id}
Get one venue
One venue with its practical profile: capacity, lockers, payment, smoking, accessibility and the rest of what a visitor asks before they go. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
id verplicht | path | string | - | The id of the resource. Events also accept their slug. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/venues/oost" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/venues/oost", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/venues/oost",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": {
"id": "oost",
"name": "OOST",
"city": "Amsterdam",
"area": "Oost",
"address": "Zeeburgerpad 1, 1018 AJ Amsterdam",
"lat": 52.3701,
"lng": 4.9412,
"website": "https://clubooost.nl",
"tags": [
"club",
"techno"
],
"rating": 4.4,
"reviews_count": 128,
"image_url": "https://partyppl.nl/media/venues/oost.jpg",
"url": "https://partyppl.nl/locatie/oost",
"info": "Ingang aan de waterkant, garderobe verplicht.",
"accessibility": "Rolstoeltoegankelijk, aangepast toilet aanwezig.",
"rules": [
"18+, legitimatie verplicht"
],
"rules_url": "https://clubooost.nl/huisregels",
"facts": {
"capacity": 1200,
"rooms": "2 zalen",
"lockers": "app",
"cashless": "pin",
"smoking": "buiten"
},
"upcoming_events": 7
},
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200Get one venue400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.404No such resource.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/artists
List artists
Performers, by name. Most of these profiles are built from the line-ups we import. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
q optioneel | query | string | - | Free text over the name. |
genre optioneel | query | string | - | Only artists whose primary genre is this. |
country optioneel | query | string | - | Only artists from this country, as the profile spells it. |
limit optioneel | query | integer1..100 | 25 | Items per page, 1 to 100. |
cursor optioneel | query | string | - | Opaque cursor from meta.next_cursor of the previous page. Do not build one yourself. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/artists?q=lens&limit=25" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/artists?q=lens&limit=25", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/artists?q=lens&limit=25",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": [
{
"id": "amelie-lens",
"name": "Amelie Lens",
"genre": "Techno",
"country": "BE",
"city": "Antwerpen",
"verified": true,
"image_url": "https://partyppl.nl/media/artists/amelie-lens.jpg",
"links": {
"spotify": "https://open.spotify.com/artist/0",
"instagram": "https://instagram.com/amelielens"
},
"url": "https://partyppl.nl/artiest/amelie-lens"
}
],
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"count": 1,
"limit": 25,
"next_cursor": null,
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200List artists400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/artists/{id}
Get one artist
One artist with their biography, their links, their discography and their next dates in NL and BE. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
id verplicht | path | string | - | The id of the resource. Events also accept their slug. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/artists/amelie-lens" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/artists/amelie-lens", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/artists/amelie-lens",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": {
"id": "amelie-lens",
"name": "Amelie Lens",
"genre": "Techno",
"country": "BE",
"city": "Antwerpen",
"verified": true,
"image_url": "https://partyppl.nl/media/artists/amelie-lens.jpg",
"links": {
"spotify": "https://open.spotify.com/artist/0",
"instagram": "https://instagram.com/amelielens"
},
"url": "https://partyppl.nl/artiest/amelie-lens",
"bio": "Belgische techno-dj en producer, oprichter van Lenske.",
"aliases": [],
"agency": null,
"releases": [
{
"title": "Hypnotized",
"year": 2020
}
],
"upcoming_events": [
{
"id": "oost-sat",
"slug": "oost-hard-techno-night",
"title": "OOST: Hard Techno Night",
"date": "2026-10-03",
"end_date": null,
"start": "23:00",
"end": "06:00",
"timezone": "Europe/Amsterdam",
"status": "approved",
"cancelled": false,
"cancel_reason": null,
"postponed_to": null,
"genres": [
"Hard techno",
"Techno"
],
"price": 18,
"price_max": 25,
"currency": "EUR",
"age": 18,
"ticket_url": null,
"artwork_url": "https://partyppl.nl/media/imports/oost/oost-sat.jpg",
"venue": {
"id": "oost",
"name": "OOST",
"city": "Amsterdam",
"address": "Zeeburgerpad 1, 1018 AJ Amsterdam",
"lat": 52.3701,
"lng": 4.9412
},
"organisation": {
"id": "oost-collective",
"name": "OOST Collective"
},
"url": "https://partyppl.nl/e/oost-hard-techno-night",
"updated_at": 1758499200
}
]
},
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200Get one artist400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.404No such resource.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/organisations
List organisations
Promoters and the programming teams of clubs, by name. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
q optioneel | query | string | - | Free text over the name. |
verified optioneel | query | boolean | - | True: only organisations we have checked. |
limit optioneel | query | integer1..100 | 25 | Items per page, 1 to 100. |
cursor optioneel | query | string | - | Opaque cursor from meta.next_cursor of the previous page. Do not build one yourself. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/organisations?q=oost&limit=25" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/organisations?q=oost&limit=25", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/organisations?q=oost&limit=25",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": [
{
"id": "oost-collective",
"name": "OOST Collective",
"verified": true,
"since": 2014,
"bio": "Hard techno in Amsterdam Oost.",
"website": "https://clubooost.nl",
"events_count": 42,
"url": "https://partyppl.nl/organisatie/oost-collective"
}
],
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"count": 1,
"limit": 25,
"next_cursor": null,
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200List organisations400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/organisations/{id}
Get one organisation
One organisation. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
id verplicht | path | string | - | The id of the resource. Events also accept their slug. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/organisations/oost-collective" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/organisations/oost-collective", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/organisations/oost-collective",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": {
"id": "oost-collective",
"name": "OOST Collective",
"verified": true,
"since": 2014,
"bio": "Hard techno in Amsterdam Oost.",
"website": "https://clubooost.nl",
"events_count": 42,
"url": "https://partyppl.nl/organisatie/oost-collective"
},
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200Get one organisation400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.404No such resource.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/genres
List genres
The fixed list of genres an event can carry, with the family each belongs to. These are the only values ?genre= accepts. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
limit optioneel | query | integer1..100 | 25 | Items per page, 1 to 100. |
cursor optioneel | query | string | - | Opaque cursor from meta.next_cursor of the previous page. Do not build one yourself. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/genres?limit=25" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/genres?limit=25", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/genres?limit=25",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": [
{
"name": "Hard techno",
"group": "Hard",
"slug": "hard-techno"
}
],
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"count": 1,
"limit": 25,
"next_cursor": null,
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200List genres400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/radar
List new releases
Radar: new singles, EPs and albums from the artists in the agenda, newest first, from the last one to four weeks. Read only. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
genre optioneel | query | string | - | Only records by artists of this genre, one of /v1/genres. |
weeks optioneel | query | integer1..4 | 4 | How many weeks back: 1, 2 or 4. |
limit optioneel | query | integer1..100 | 25 | Items per page, 1 to 100. |
cursor optioneel | query | string | - | Opaque cursor from meta.next_cursor of the previous page. Do not build one yourself. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/radar?genre=Techno&limit=25" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/radar?genre=Techno&limit=25", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/radar?genre=Techno&limit=25",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": [
{
"title": "The Resistance EP",
"type": "ep",
"release_date": "2026-09-24",
"genre": "Techno",
"artists": [
{
"id": "charlotte-de-witte",
"name": "Charlotte de Witte",
"url": "https://partyppl.nl/artiest/charlotte-de-witte"
}
],
"spotify_url": null,
"deezer_url": "https://www.deezer.com/album/123456789",
"cover_url": "https://partyppl.nl/media/artists/charlotte-de-witte-rel-1a2b3c4d.jpg",
"next_event": {
"id": "ev_7k2m",
"title": "Awakenings Upclose",
"date": "2026-10-17",
"city": "Amsterdam",
"url": "https://partyppl.nl/e/awakenings-upclose-2026"
}
}
],
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"count": 1,
"limit": 25,
"next_cursor": null,
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200List new releases400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/badges
The badge catalogue
Every badge somebody can earn on PartyPPL, with its family, its rung and what it takes, in Dutch and English. Every rule is checked against what a person has actually been to or contributed: nights that have happened, cities, rooms, genres attended, festivals, friends, corrections the agenda team applied, answers somebody else found useful. Nothing here is read from a setting somebody ticked, and nothing rewards volume of posting or money spent. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
limit optioneel | query | integer1..100 | 25 | Items per page, 1 to 100. |
cursor optioneel | query | string | - | Opaque cursor from meta.next_cursor of the previous page. Do not build one yourself. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/badges?limit=25" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/badges?limit=25", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/badges?limit=25",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": [
{
"id": "nacht-25",
"family": "nights",
"tier": 25,
"mark": "25",
"name": {
"nl": "25 nachten",
"en": "25 nights"
},
"description": {
"nl": "Vijfentwintig nachten geweest",
"en": "Twenty-five nights out"
},
"counts": "nights",
"needs": 25
}
],
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"count": 1,
"limit": 25,
"next_cursor": null,
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200The badge catalogue400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/users/{id}/badges
The badges one person has
The badges of one public profile, addressed by handle or by id, with the date each one was earned and the number behind it at that moment. Badges are personal data and this follows the profile exactly: a private account, a suspended account and an account that does not exist all answer 404, because saying which of the three it is would itself be telling you something about somebody. Nothing in the answer says what they have not earned.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
id verplicht | path | string | - | The id of the resource. Events also accept their slug. |
limit optioneel | query | integer1..100 | 25 | Items per page, 1 to 100. |
cursor optioneel | query | string | - | Opaque cursor from meta.next_cursor of the previous page. Do not build one yourself. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/users/oost-sat/badges?limit=25" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/users/oost-sat/badges?limit=25", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/users/oost-sat/badges?limit=25",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": [
{
"id": "nacht-25",
"family": "nights",
"tier": 25,
"name": {
"nl": "25 nachten",
"en": "25 nights"
},
"description": {
"nl": "Vijfentwintig nachten geweest",
"en": "Twenty-five nights out"
},
"value": 27,
"earned_at": 1789654255
}
],
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"count": 1,
"limit": 25,
"next_cursor": null,
"user": {
"id": "u_noor",
"handle": "noor",
"name": "Noor",
"url": "https://partyppl.nl/u/noor"
},
"catalogue": 40
}
}Statussen
200The badges one person has400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.404No such resource.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.
GET/cities
List cities
Every city with at least one event coming up, busiest first, with the number of events and the middle of that city's venues. Needs a token with the read scope. A read token is free: create one in the organiser portal under API. Browsing the site itself needs nothing.
Parameters
| Naam | In | Type | Standaard | Uitleg |
|---|---|---|---|---|
country optioneel | query | NL | BE | - | Only cities in this country. |
limit optioneel | query | integer1..100 | 25 | Items per page, 1 to 100. |
cursor optioneel | query | string | - | Opaque cursor from meta.next_cursor of the previous page. Do not build one yourself. |
Voorbeeldverzoek
curl -s "https://api.partyppl.nl/v1/cities?country=NL&limit=25" \
-H "Authorization: Bearer $PPL_TOKEN"const res = await fetch("https://api.partyppl.nl/v1/cities?country=NL&limit=25", {
headers: {
Authorization: `Bearer ${process.env.PPL_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data, meta } = await res.json();import os
import requests
res = requests.get(
"https://api.partyppl.nl/v1/cities?country=NL&limit=25",
headers={"Authorization": f"Bearer {os.environ['PPL_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
payload = res.json()Toon het voorbeeldantwoord
{
"data": [
{
"name": "Amsterdam",
"country": "NL",
"upcoming_events": 312,
"lat": 52.3702,
"lng": 4.8952,
"url": "https://partyppl.nl/stad/amsterdam"
}
],
"meta": {
"request_id": "9f1c2b4a-7e3d-4a10-9c2f-6b8d1e5a0c33",
"count": 1,
"limit": 25,
"next_cursor": null,
"attribution": {
"text": "Event data from PartyPPL. Link back to the event page on partyppl.nl.",
"url": "https://partyppl.nl",
"terms": "https://api.partyppl.nl/v1/terms"
}
}
}Statussen
200List cities400The request is wrong.error.details.paramsnames every bad parameter.401No token, or a token we do not know.403The token is valid but does not carry thereadscope, or the organisation is suspended.429Over the per-minute limit or the daily quota.Retry-Aftersays how long to wait.500Something went wrong on our side. Quoterequest_id.