---
title: "API Best Practices &amp; Usage"
description: "Build reliable, secure, and performant integrations with Schiphol APIs. Covers rate limiting, token management, caching, error handling, security, and testing."
url: "https://developer.schiphol.nl/news-and-updates/api-best-practices"
image: "https://developer.schiphol.nl/_og/d/c_Ocean.takumi,title_~QVBJIEJlc3QgUHJhY3RpY2VzICYgVXNhZ2U,description_~QnVpbGQgcmVsaWFibGUsIHNlY3VyZSwgYW5kIHBlcmZvcm1hbnQgaW50ZWdyYXRpb25zIHdpdGggU2NoaXBob2wgQVBJcy4gQ292ZXJzIHJhdGUgbGltaXRpbmcsIHRva2VuIG1hbmFnZW1lbnQsIGNhY2hpbmcsIGVycm9yIGhhbmRsaW5nLCBzZWN1cml0eSwgYW5kIHRlc3Rpbmcu,props_eyJ0aGVtZSI6eyJtb2RlIjoibGlnaHQiLCJjb2xvcnMiOnt9fX0,p_Ii9uZXdzLWFuZC11cGRhdGVzL2FwaS1iZXN0LXByYWN0aWNlcyI,s_9RTYe4rTBRPlfQMw.png"
---

[← Back to News & Updates](https://developer.schiphol.nl/news-and-updates)

Best Practices

July 22, 2026

API Best Practices & Usage

By Schiphol API Team

![API Best Practices - Data Flow Diagram](https://images.ctfassets.net/9bvisqn57bx6/4xsQhE5HeUsahpt0N6zSHd/1738cfbc901a5739750f5341cb7ec0e7/data_flow_process_diagram.svg)

Best Practices

Six areas every API integration should get right

1

Rate Limiting

Understand per-tier limits, monitor quota headers, and implement exponential backoff with jitter.

Performance

2

Token Management

Cache tokens, refresh proactively 60 s before expiry, and use thread-safe storage in concurrent apps.

Reliability

3

Caching

Match cache TTL to data freshness - from 24 h for static data to 15 s for real-time status.

Performance

4

Error Handling

Handle every HTTP status code and design with circuit breakers and graceful fallbacks.

Reliability

5

Security

Store secrets in a vault, use per-environment credentials, and rotate regularly.

Security

6

Testing

Validate your integration end-to-end: token flow, error handling, retries, and timeouts before going to production.

Quality

Building robust integrations with Schiphol APIs requires following patterns that ensure reliability, performance, and a smooth experience for your users. This guide covers the essential practices every developer should apply - whether you are building a new integration from scratch or hardening an existing one.

## [1\. Rate Limiting](#_1-rate-limiting)

All Schiphol APIs enforce rate limits per application to ensure fair usage and platform stability. Exceeding a limit returns a `429 Too Many Requests` response with a `Retry-After` header indicating how long to wait.

| Tier   | Rate Limit            | Notes                                               |
| :----- | :-------------------- | :-------------------------------------------------- |
| Public | 100 requests / minute | Suitable for display and informational applications |

## [2\. Token Management](#_2-token-management)

OAuth 2.0 access tokens are valid for **30 minutes**. Mismanaging tokens is the most common cause of `401 Unauthorized` errors in production.

1

Request a token once - then cache and reuse it

Never request a new token for every API call. A single token is valid for 30 minutes and should serve all requests within that window. Requesting a new token per call wastes Auth0 quota and adds 100-200 ms latency to every request.

2

Refresh proactively - 60 seconds before expiry

Read `expires_in` from the token response (usually 1800 s = 30 min). Schedule a background refresh 60 s before the token expires. This ensures you always have a valid token ready and avoids in-flight requests receiving a 401.

3

Use thread-safe storage in concurrent applications

In multi-threaded or async apps, protect token state with a mutex or lock. Without synchronisation, multiple threads may all detect token expiry simultaneously and each request a new token - this is the "token stampede" problem and will hit Auth0 rate limits.

4

Store Client Secret in a secrets manager

Never hardcode Client ID or Client Secret in source code or config files. Use Azure Key Vault, HashiCorp Vault, or environment variables. Rotate secrets at least every 90 days and immediately if a secret is exposed.

Token stampede warning

In high-concurrency systems, if the token expires and 50+ threads all detect it simultaneously, they may all try to refresh at once. Use a single background token-refresh worker and share the token reference with all threads via a read-write lock.

## [3\. Caching Strategies](#_3-caching-strategies)

Caching is the single most effective way to reduce API call volume, lower latency, and stay within rate limits. Different data types have different freshness requirements - match your TTL to the data, not to a single global setting.

| Data Type                                                      | Recommended TTL | Notes                                                        |
| :------------------------------------------------------------- | :-------------- | :----------------------------------------------------------- |
| Static reference data - airlines, destinations, aircraft types | 24 hours        | Changes very rarely; safe to cache aggressively              |
| Flight schedules                                               | 5-15 minutes    | Changes a few times per day; short TTL is sufficient         |
| Flight status - gate, delay, boarding                          | 30-60 seconds   | Time-sensitive; keep cache short                             |
| Real-time arrivals / departures                                | 15-30 seconds   | Even a 15 s cache dramatically cuts repeated identical calls |
| User-specific / subscription data                              | Do not cache    | Never share personalised data across callers                 |

Application-level vs. per-user caches+

Flight schedule and status data is the same for all users - cache it at the application level and serve all users from a single cache entry. Never cache data that contains user-specific subscription or authorisation information in a shared cache.

Stale-while-revalidate pattern+

For non-critical data, serve the stale cached version immediately while refreshing in the background. This eliminates cache-miss latency spikes at TTL boundaries. Suitable for flight schedules and reference data - do not use for real-time status data where freshness is critical.

## [4\. Error Handling](#_4-error-handling)

Robust error handling ensures your application degrades gracefully rather than failing hard when the API returns an unexpected response. Design every integration to handle failure as a first-class concern.

| Status  | Meaning             | Recommended Action                                                        |
| :------ | :------------------ | :------------------------------------------------------------------------ |
| 200-299 | Success             | Process the response normally                                             |
| 304     | Not Modified        | Use your cached copy - nothing has changed                                |
| 400     | Bad Request         | Fix the request (invalid parameter, missing field) - do not retry as-is   |
| 401     | Unauthorized        | Refresh the access token and retry the request once                       |
| 403     | Forbidden           | Check subscription status - approval may be pending; contact the API team |
| 404     | Not Found           | Validate the flight number, ID, or resource path                          |
| 429     | Too Many Requests   | Back off exponentially; always honour the Retry-After header              |
| 500     | Server Error        | Retry with exponential backoff - do not try to fix in the client          |
| 503     | Service Unavailable | The service is temporarily down; retry after the Retry-After period       |

Design for failure from the start

Treat every external API call as potentially failing. Use **timeouts** (5 s connect / 10 s read), **circuit breakers** to stop calling a failing API, and **fallback values** so a temporary API issue does not cascade into a full application outage.

Which errors are safe to retry?+

**Safe to retry (with backoff):** `429`, `500`, `502`, `503`, `504`, and network timeouts.

**Do not retry:** `400` (fix your request first), `401` (refresh token then retry once), `403` (subscription issue - retrying won't help), `404` (resource does not exist).

## [5\. API Versioning](#_5-api-versioning)

Always pin your integration to a specific API version. Calling an unversioned endpoint may result in silent breaking changes when we release a new major version.

-   Specify the version in the URL path: `/public-flights/v4/flights`
-   Subscribe to the [News & Updates](https://developer.schiphol.nl/news-and-updates) page for version announcements and deprecation notices
-   Allow at least 2 weeks of parallel testing before switching your production integration

Version support policy

We support each major API version for at least **18 months** after the next version is released. Deprecation notices are published at least **6 months** before end-of-life. You will never wake up to a surprise breaking change.

## [6\. Security](#_6-security)

Credential exposure is the most common security incident in API integrations. Follow these rules without exception.

Do

-   Store Client ID & Secret in a secrets manager (Azure Key Vault, HashiCorp Vault)
-   Use separate credentials per environment (dev, test, production)
-   Rotate secrets at least every 90 days
-   Revoke and reissue immediately if a secret is exposed
-   Validate and sanitise all API response data before using it

Don't

-   Hardcode secrets in source code or config files
-   Commit secrets to version control - even private repos
-   Expose the Client Secret in client-side JavaScript or mobile apps
-   Share one credential set across multiple teams or environments
-   Log access tokens or secrets in application logs or error messages

## [7\. Performance Tips](#_7-performance-tips)

Small optimisations compound. Use the following patterns to get the most performance out of every API call.

Use pagination and field filtering+

Most list endpoints support `page` and `pageSize` parameters. Always paginate large result sets - fetching everything in one call is wasteful and slow. Where the API supports field selection, request only the fields your application uses. Smaller payloads are faster and cheaper on bandwidth.

GET /public/public-flights/v4/flights?page=0&pageSize=20

Set connection and read timeouts+

Always configure explicit timeouts on your HTTP client. Without them, a slow or hung response will block a thread indefinitely and exhaust your thread pool.

Recommended: **5 s connection timeout** · **10 s read timeout**. If your use case requires longer timeouts (e.g. large schedule downloads), set them explicitly and log slow responses for monitoring.

Reuse HTTP connections (Keep-Alive / connection pooling)+

Establishing a new TLS connection for every request adds 100-300 ms of overhead. Use an HTTP client that supports keep-alive and connection pooling. Most popular libraries handle this automatically when you reuse the client instance:

-   **Python:** use a `requests.Session()` object
-   **Java:** use `WebClient` or a shared `OkHttpClient`
-   **Node.js:** `axios` and `node-fetch` reuse connections by default

## [8\. Testing & Environments](#_8-testing-environments)

Validate your integration end-to-end before going live. Test token acquisition, error handling, retries, and edge cases with low-volume calls against the production environment.

PRD API basehttps://api.schiphol.nl

PRD token endpointhttps://api.auth.schiphol.nl/oauth/token

What to test before going to production+

Run the following checklist before going live:

-   Token acquisition and automatic refresh works correctly
-   All expected HTTP status codes (200, 401, 403, 429, 500) are handled
-   Exponential backoff fires correctly on 429 and 5xx responses
-   Responses are parsed correctly for edge cases (empty arrays, null fields)
-   Timeouts are configured and do not hang the application
-   Caching returns fresh data and does not serve stale responses indefinitely
-   No secrets or tokens appear in application logs

## [What's next?](#whats-next)

[

Getting Started Guide

New to the platform? Set up credentials and make your first authenticated API call.](https://developer.schiphol.nl/news-and-updates/api-consumer-getting-started-guide)[

Migration Guide

Coming from 3scale? Update your endpoint URLs and switch to OAuth 2.0.](https://developer.schiphol.nl/news-and-updates/api-consumer-migration-guide)[

API Catalogue

Browse all available APIs, endpoint references, and OpenAPI schemas.](https://developer.schiphol.nl/apis)[

My Applications

Manage your API applications, subscriptions, and credentials in one place.](https://developer.schiphol.nl/apps)

### [Flights](#flights)

-   [Departures](https://www.schiphol.nl/en/departures/)
-   [Arrivals](https://www.schiphol.nl/en/arrivals/)
-   [Transfers](https://www.schiphol.nl/en/transfers/)

### [Things to do at Schiphol](#things-to-do-at-schiphol)

-   [Shop](https://www.schiphol.nl/en/at-schiphol/shop/)
-   [Eat and drink](https://www.schiphol.nl/en/at-schiphol/eat-and-drink/)
-   [Airport maps](https://www.schiphol.nl/en/airport-maps/)
-   [Services](https://www.schiphol.nl/en/services/)

### [Check-in](#check-in)

-   [Ways to check in](https://www.schiphol.nl/en/check-in/)
-   [Baggage rules and checks](https://www.schiphol.nl/en/baggage/)
-   [How busy is Schiphol](https://www.schiphol.nl/en/busy/)

### [Traveling to and from Schiphol](#traveling-to-and-from-schiphol)

-   [All parking options](https://www.schiphol.nl/en/parking/)
-   [All travel options](https://www.schiphol.nl/en/from-to-schiphol/)
-   [Short-term parking](https://www.schiphol.nl/en/parking/short-term/)
-   [Long term parking](https://www.schiphol.nl/en/parking/long-term/)
-   [Pick-up & drop-off](https://www.schiphol.nl/en/pick-up-and-drop-off/)

### [All Schiphol websites](#all-schiphol-websites)

-   [Royal Schiphol Group](https://www.royalschipholgroup.com/)
-   [Sustainability](https://www.schiphol.nl/en/sustainability/)
-   [Operations](https://www.schiphol.nl/en/operations/)
-   [Schiphol as a neighbour](https://www.schiphol.nl/en/schiphol-as-a-neighbour/)
-   [Careers at Schiphol Group](https://werkenbijschiphol.nl/)
-   [You and Schiphol](https://www.schiphol.nl/en/you-and-schiphol/)
-   [Developer Center](https://developer.schiphol.nl/)

![Developer Portal](https://developer.schiphol.nl/_core/api/v3/assets/logo?ref=1763460379699) © Schiphol 2025

-   [Privacy](https://www.schiphol.nl/en/privacy/)
-   [Schiphol regulations](https://www.schiphol.nl/en/regulations/)
-   [Accessibility](https://www.schiphol.nl/en/accessibility/)
-   [Disclaimer](https://www.schiphol.nl/en/disclaimer/)
-   [Newsletter](https://www.schiphol.nl/en/newsletter/)
-   [Contact us](https://www.schiphol.nl/en/contact/)