X: 000.00
Y: 000.00
18+ ONLY // RESTRICTED ACCESS

FOR BOTS, SITES, AND VR TOOLS

Plane API

Pull upcoming Plane events as JSON, check the stream banner, or subscribe a webhook for update notifications. Read endpoints are public and do not need an API key.

Base URL: https://plane.fm/api/v1

Quick start

Upcoming events with curl

curl "https://plane.fm/api/v1/events?limit=10"

Upcoming events with JavaScript

const response = await fetch(
  "https://plane.fm/api/v1/events?limit=10"
);
const { data } = await response.json();

Live sample not loaded yet.

Read endpoints

MethodPathUse
GET/api/v1/eventsList live and upcoming events by default.
GET/api/v1/events/nextGet the current event, or the next one. Cancelled events are skipped.
GET/api/v1/streamGet the public stream banner settings and status.
GET/api/v1List API links.
GET/api/flightsLegacy schedule response: { "flights": [...] }.
GET/api/streamLegacy stream response used by the homepage.

Event filters

ParameterValuesDefault
scopeupcoming, live, past, allupcoming
limitInteger from 1 to 10050
fromISO 8601 date or date-timeNo start filter
toISO 8601 date or date-timeNo end filter

Events are sorted by departure.

{
  "object": "list",
  "count": 1,
  "scope": "upcoming",
  "limit": 50,
  "data": [
    {
      "flightNo": "WF0289",
      "destination": "Paw Beach",
      "lineup": "Nana_Wunsek, GrizzMango, RileyPie, Valryus",
      "eventInfoUrl": null,
      "departure": "2026-11-07T06:00:00.000Z",
      "landing": "2026-11-07T11:00:00.000Z",
      "status": "ON TIME",
      "scheduledStatus": "ON TIME",
      "state": "upcoming"
    }
  ]
}

Responses are cacheable for 15 seconds and include an ETag. Send If-None-Match on later requests to get 304 Not Modified when nothing changed. Errors use { "error": { "code": "...", "message": "..." } }.

Webhook notifications

Plane can POST JSON to a webhook URL you control when the schedule or stream settings change. Discord and Slack show the content field as a message.

Events

schedule.published
An admin saved a changed schedule.
stream.updated
An admin saved changed stream settings.

How signup works

  1. Discord and Slack webhook URLs activate after Plane sends a test message.
  2. Any other HTTPS endpoint receives a one-time code. Enter the code below to activate it.
  3. Keep the manage token returned after activation. It is required to unsubscribe.

Subscribe

Send me

Payload and verification

Example delivery

{
  "id": "8e33c396-02c4-4a31-91e8-7988e7630dd0",
  "type": "schedule.published",
  "createdAt": "2026-11-06T21:30:00.000Z",
  "data": {
    "eventCount": 18,
    "nextEvent": { "flightNo": "WF0289" },
    "eventsUrl": "https://plane.fm/api/v1/events"
  },
  "content": "Plane schedule updated. Next: WF0289, Paw Beach, Sat, 07 Nov 2026 06:00:00 GMT. https://plane.fm/"
}

Delivery rules

  • Return any 2xx status to accept a delivery.
  • Each attempt times out after 5 seconds.
  • Failed deliveries retry every 5 minutes for up to an hour.
  • Subscriptions are disabled after 10 deliveries fail after all retries.

Verify the signature

For a custom receiver, verify X-Plane-Signature with the signing secret returned at signup. The value is sha256= plus the HMAC-SHA256 hex digest of the exact request body.

import { createHmac, timingSafeEqual } from "node:crypto";

const expected = "sha256=" + createHmac("sha256", signingSecret)
  .update(rawBody)
  .digest("hex");
const received = request.headers["x-plane-signature"];
const valid = received.length === expected.length
  && timingSafeEqual(Buffer.from(received), Buffer.from(expected));

Unsubscribe