The Skateparks.world REST API provides programmatic access to skatepark data. All endpoints require authentication.
Authentication Required
All API endpoints are protected. You must include a valid API key with every request. Contact api@skateparks.world to request access.
Include your API key in every request using one of these methods:
X-API-Key: your_api_key_hereAuthorization: Bearer your_api_key_herecurl -X GET "https://skateparks.world/api/v1/parks" \
-H "X-API-Key: your_api_key_here"All API endpoints are relative to:
https://skateparks.world/api/v1The API uses standard HTTP status codes. Errors return a JSON object with an error field.
| Status | Meaning |
|---|---|
200 | Success |
201 | Resource created |
400 | Bad request — missing or invalid parameters |
401 | Unauthorized — invalid or missing API key |
404 | Resource not found |
500 | Internal server error |
{
"error": "Unauthorized"
}A park has the following fields. All fields except the three marked required are optional when creating or updating.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Required | Name of the skatepark. |
country | string | Required | Country name (e.g. "Denmark"). |
city | string | Required | City name (e.g. "Copenhagen"). |
slug | string | Optional | URL slug. Auto-generated from name + city if omitted. |
alias | string | Optional | Alternative/local name for the park. |
| Parameter | Type | Required | Description |
|---|---|---|---|
streetAddress | string | Optional | Street address. |
zipcode | string | Optional | Postal/zip code. |
lat | number | Optional | Latitude coordinate. |
lng | number | Optional | Longitude coordinate. |
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | Optional | "indoor", "outdoor", "both", or "unknown" (default). |
status | string | Optional | "open", "closed", "under_construction", or "unknown" (default). |
ownership | string | Optional | Who owns the park (e.g. "Municipal", "Private"). |
management | string | Optional | Who manages/operates the park. |
builtBy | string | Optional | Construction company or builder. |
designedBy | string | Optional | Park designer. |
| Parameter | Type | Required | Description |
|---|---|---|---|
obstacles | string[] | Optional | e.g. ["halfpipe", "quarterpipe", "rail", "ledge", "bowl", "funbox"]. |
facilities | string[] | Optional | e.g. ["lights", "toilets", "parking", "water", "shop", "rental"]. |
sports | string[] | Optional | e.g. ["skateboarding", "bmx", "scooter", "inline"]. |
surface | string[] | Optional | e.g. ["concrete", "wood", "asphalt", "metal"]. |
requirements | string[] | Optional | e.g. ["helmet", "pads", "membership"]. |
| Parameter | Type | Required | Description |
|---|---|---|---|
sizeSqm | number | Optional | Park area in square meters. |
yearBuilt | number | Optional | Year the park was built. |
| Parameter | Type | Required | Description |
|---|---|---|---|
website | string | Optional | Park website URL. |
phone | string | Optional | Phone number. |
email | string | Optional | Contact email address. |
facebook | string | Optional | Facebook page URL. |
instagram | string | Optional | Instagram handle or URL. |
youtube | string | Optional | YouTube channel URL. |
| Parameter | Type | Required | Description |
|---|---|---|---|
priceAmount | number | Optional | Entry price (e.g. 10.00). Null if free. |
priceCurrency | string | Optional | ISO 4217 currency code (e.g. "USD", "EUR", "DKK"). |
paymentMethods | string[] | Optional | e.g. ["cash", "card", "mobilepay"]. |
membershipAvailable | boolean | Optional | Whether membership/season pass is available. |
| Parameter | Type | Required | Description |
|---|---|---|---|
supervised | boolean | Optional | Whether staff supervision is available. |
surveilled | boolean | Optional | Whether the park has camera surveillance. |
hours | object | Optional | Opening hours. See format below. |
// hours format — each day is { open, close } or null (closed)
{
"mon": { "open": "08:00", "close": "22:00" },
"tue": { "open": "08:00", "close": "22:00" },
"wed": { "open": "08:00", "close": "22:00" },
"thu": { "open": "08:00", "close": "22:00" },
"fri": { "open": "08:00", "close": "23:00" },
"sat": { "open": "10:00", "close": "23:00" },
"sun": null // closed on Sunday
}| Parameter | Type | Required | Description |
|---|---|---|---|
shortDescription | string | Optional | Brief summary of the park. |
description | string | Optional | Full description. Supports newlines. |
| Parameter | Type | Required | Description |
|---|---|---|---|
id | uuid | Optional | Unique park ID. Auto-generated. |
countrySlug | string | Optional | Auto-generated from country. |
citySlug | string | Optional | Auto-generated from city. |
averageRating | number | Optional | Computed average rating (1-5). |
ratingCount | number | Optional | Total number of ratings. |
viewCount | number | Optional | Page view count. |
featured | boolean | Optional | Whether the park is featured. |
verified | boolean | Optional | Whether location has been verified. |
createdAt | timestamp | Optional | ISO 8601 creation date. |
updatedAt | timestamp | Optional | ISO 8601 last update date. |
images | array | Optional | Related images (included in GET by ID). |
videos | array | Optional | Related videos (included in GET by ID). |
/api/v1/parksList all parks with pagination, or search by query.
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Optional | Search query. If provided, returns matching parks instead of all. |
page | number | Optional | Page number (default: 1). |
limit | number | Optional | Results per page. Min 1, max 100 (default: 50). |
{
"parks": [ { "id": "...", "name": "...", ... } ],
"pagination": {
"page": 1,
"limit": 50,
"total": 1234,
"totalPages": 25
}
}/api/v1/parksCreate a new skatepark. Only name, country, and city are required. All other park fields (see Park Object above) can be included.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Required | Name of the skatepark. |
country | string | Required | Country name. |
city | string | Required | City name. |
Plus any optional fields from the Park Object reference above (obstacles, facilities, phone, email, hours, pricing, etc.).
{
"name": "Faelledparken Skatepark",
"country": "Denmark",
"city": "Copenhagen",
"lat": 55.6945,
"lng": 12.5728,
"type": "outdoor",
"status": "open",
"obstacles": ["bowl", "quarterpipe", "rail", "ledge"],
"facilities": ["lights", "parking"],
"sports": ["skateboarding", "scooter"],
"surface": ["concrete"],
"phone": "+45 12345678",
"email": "info@example.com",
"instagram": "@faelledskatepark",
"description": "A popular outdoor skatepark in the heart of Copenhagen."
}{
"park": { "id": "...", "name": "Faelledparken Skatepark", "slug": "faelledparken-skatepark-copenhagen", ... }
}/api/v1/parks/:idGet a single park by ID with all details, images, and videos.
{
"park": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Faelledparken Skatepark",
"slug": "faelledparken-skatepark-copenhagen",
"country": "Denmark",
"city": "Copenhagen",
"streetAddress": "Øster Allé 1",
"zipcode": "2100",
"lat": 55.6945,
"lng": 12.5728,
"type": "outdoor",
"status": "open",
"obstacles": ["bowl", "quarterpipe", "rail", "ledge"],
"facilities": ["lights", "parking"],
"sports": ["skateboarding", "scooter"],
"surface": ["concrete"],
"phone": "+45 12345678",
"email": "info@example.com",
"website": "https://example.com",
"instagram": "@faelledskatepark",
"facebook": "",
"youtube": "",
"priceAmount": null,
"priceCurrency": "",
"paymentMethods": [],
"membershipAvailable": null,
"supervised": false,
"surveilled": false,
"hours": null,
"sizeSqm": 1200,
"yearBuilt": 2018,
"shortDescription": "Popular concrete park in central Copenhagen.",
"description": "A popular outdoor skatepark in the heart of Copenhagen...",
"averageRating": "4.20",
"ratingCount": 15,
"verified": true,
"images": [
{ "id": "...", "url": "https://...", "caption": "...", "credit": "...", "order": 0 }
],
"videos": [],
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2025-11-20T14:22:00.000Z"
}
}/api/v1/parks/:idUpdate an existing park. Send only the fields you want to change. Accepts any field from the Park Object.
{
"phone": "+45 87654321",
"email": "new@example.com",
"instagram": "@newhandle",
"obstacles": ["bowl", "halfpipe", "rail", "ledge", "funbox"],
"hours": {
"mon": { "open": "10:00", "close": "20:00" },
"tue": { "open": "10:00", "close": "20:00" },
"wed": { "open": "10:00", "close": "20:00" },
"thu": { "open": "10:00", "close": "20:00" },
"fri": { "open": "10:00", "close": "22:00" },
"sat": { "open": "10:00", "close": "22:00" },
"sun": null
},
"priceAmount": 5.00,
"priceCurrency": "EUR"
}{
"park": { "id": "...", "name": "...", ... }
}/api/v1/parks/:idPermanently delete a park and all related images, videos, and ratings.
{ "success": true }/api/v1/searchSearch parks by name, city, or country.
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Required | Search query (must be non-empty). |
limit | number | Optional | Max results. Min 1, max 50 (default: 20). |
{
"parks": [ { "id": "...", "name": "...", ... } ],
"query": "copenhagen",
"count": 5
}/api/v1/parks/coordinatesGet coordinates for all parks. Useful for rendering map markers. Cached for 1 hour.
{
"parks": [
{ "id": "...", "name": "...", "lat": 55.67, "lng": 12.56, ... },
...
]
}/api/v1/parks/:id/ratingsSubmit a rating for a park. Rate-limited by IP address.
| Parameter | Type | Required | Description |
|---|---|---|---|
rating | number | Required | Rating value, 1 to 5. |
displayName | string | Required | Name to display with the review. |
comment | string | Optional | Optional review text. |
email | string | Optional | Optional email (not displayed publicly). |
createdAt | string | Optional | ISO 8601 timestamp. Defaults to now. Use this to backdate ratings found online (e.g. "2023-06-15T12:00:00Z"). |
{
"rating": {
"id": "...",
"parkId": "...",
"rating": 4,
"displayName": "Alex",
"comment": "Great park!",
...
}
}/api/v1/parks/:id/imagesUpload a photo for a park. Uses multipart/form-data. New uploads start with pending status (moderation required).
| Parameter | Type | Required | Description |
|---|---|---|---|
image | File | Required | Image file. Must be an image/* MIME type, max 10 MB. |
email | string | Required | Uploader email (for moderation contact). |
caption | string | Optional | Optional image caption/alt text. |
credit | string | Optional | Photographer credit / copyright attribution. |
curl -X POST "https://skateparks.world/api/v1/parks/:id/images" \
-H "X-API-Key: your_api_key_here" \
-F "image=@photo.jpg" \
-F "email=user@example.com" \
-F "caption=Front view of the park" \
-F "credit=John Doe"{
"image": {
"id": "...",
"parkId": "...",
"url": "https://...",
"caption": "Front view of the park",
"credit": "John Doe",
"status": "pending",
...
}
}/api/v1/suggestionsList all pending suggestions.
{
"suggestions": [
{
"id": "...",
"parkId": "...",
"changeType": "update",
"changes": { ... },
"source": "user",
"status": "pending",
...
}
]
}/api/v1/suggestionsSubmit a suggestion for a new park or changes to an existing one.
| Parameter | Type | Required | Description |
|---|---|---|---|
changes | object | Required | Object describing the proposed changes. |
changeType | string | Required | Type of change, e.g. "update", "new_park", "correction". |
parkId | string | Optional | ID of the existing park (if updating). |
source | string | Optional | Source of the suggestion (default: "user"). |
sourceUrl | string | Optional | URL reference for the data source. |
submittedBy | string | Optional | Name of the submitter. |
email | string | Optional | Contact email. |
{
"suggestion": {
"id": "...",
"changeType": "update",
"changes": { ... },
"source": "user",
"status": "pending",
...
}
}/api/v1/revalidateBust the Next.js cache for specific pages or the entire site. Call this after creating or updating parks to see changes immediately.
Provide either path or all, not both.
| Parameter | Type | Required | Description |
|---|---|---|---|
path | string | Optional | Specific page path to revalidate, e.g. "/denmark/copenhagen/park-name". |
all | boolean | Optional | Set to true to revalidate all pages. |
// Revalidate a specific park page
{ "path": "/denmark/copenhagen/faelledparken" }
// Revalidate the homepage
{ "path": "/" }
// Revalidate everything
{ "all": true }// Specific path
{ "revalidated": true, "path": "/denmark/copenhagen/faelledparken" }
// All pages
{ "revalidated": true, "scope": "all" }Rate limiting
Rating submissions are rate-limited by IP address to prevent abuse.
Image moderation
Uploaded images start with a pending status and require approval before they appear publicly.
Cache behavior
Park pages are statically generated and cached. After creating or updating data, call the revalidation endpoint to see changes reflected on the site immediately.
Content-Type
All endpoints accept and return application/json, except the image upload endpoint which uses multipart/form-data.
Need an API key or have questions? api@skateparks.world