Announcements API

Overview

The Announcements API returns the latest active announcement for app display. It is designed for in-app cards, banners, or update modals and includes rich-content fields such as summary text, cover image, gallery images, and action links.

Authentication Required

Both announcementsLatest and announcementAck require a valid Bearer JWT in the Authorization header. The JWT is obtained via the login endpoint.

Naming Convention

Announcement object fields are returned in camelCase (for example coverImageUrl, actionLinks). Keep your model mapping aligned with this.

Server-Side Seen Tracking

The API tracks the last acknowledged announcement per user on the server, so the seen flag is consistent across all of the user's devices. Call announcementAck once the user has dismissed or viewed the announcement.

Get Latest Announcement

POST /api

Returns exactly one record: the most recent announcement where is_active = 1, publishedAt <= now, and expiresAt is either null or in the future.

Request Parameters

Parameter Type Required Description
query string Required Must be "announcementsLatest"
Authorization header string Required Bearer JWT token obtained from the login endpoint.

cURL Example

cURL
curl -X POST "https://api.virtualperformancetool.com/api" \
  -H "Content-Type: application/json" \
  -H "X-API-Version: 1.3.6" \
  -H "Authorization: Bearer <jwt>" \
  -d '{
    "query": "announcementsLatest"
  }'

Response (announcement exists)

JSON
{
  "apiVersion": "1.3.6",
  "success": true,
  "announcement": {
    "id": "12",
    "title": "VPT 4.0 Released",
    "summary": "A short summary for list/cards.",
    "body": "### Full details\nSupports markdown or plain text.",
    "bodyFormat": "markdown",
    "contentLabel": "Read changelog",
    "contentUrl": "https://www.virtualperformancetool.com/changelog",
    "coverImageUrl": "https://api.virtualperformancetool.com/admin/assets/uploads/announcements/announcement_12_cover_20260415_111500_123456.jpg",
    "galleryImages": [
      {
        "url": "https://api.virtualperformancetool.com/admin/assets/uploads/announcements/announcement_12_gallery_20260415_111530_654321.jpg",
        "caption": "Cockpit view",
        "altText": "A220 cockpit"
      }
    ],
    "actionLinks": [
      {
        "label": "Update now",
        "url": "https://www.virtualperformancetool.com/download"
      }
    ],
    "publishedAt": "2026-04-10 09:00:00",
    "expiresAt": "2026-05-10 09:00:00",
    "seen": false
  }
}

Response (no active announcement)

JSON
{
  "apiVersion": "1.3.6",
  "success": true,
  "announcement": null
}

Response Fields

When available, announcement contains the fields below. Nullable fields may be null or empty arrays depending on editorial content.

Field Type Description
id string Announcement identifier.
title string Main headline.
summary string|null Short teaser text for compact layouts.
body string|null Detailed content body.
bodyFormat string Content format hint. Current values: markdown, html, plain.
contentLabel string|null Primary CTA label shown as a button text.
contentUrl string|null Primary CTA target URL.
coverImageUrl string|null Main hero/cover image URL.
galleryImages array Optional image list. Each item may include url, caption, and altText.
actionLinks array Optional list of secondary links. Each item has label and url.
publishedAt string Publication timestamp in YYYY-MM-DD HH:MM:SS.
expiresAt string|null Optional expiration timestamp. null means no auto-expiration.
seen boolean true if the authenticated user has already acknowledged this announcement via announcementAck. Use this to suppress the announcement UI without any client-side storage.

Acknowledge Announcement

POST /api

Marks an announcement as seen for the authenticated user. The server stores the highest acknowledged id — calling this with an older ID than already stored has no effect, so it is safe to call redundantly.

Authentication Required

This endpoint requires a valid Bearer JWT in the Authorization header.

Request Parameters

Parameter Type Required Description
query string Required Must be "announcementAck"
data.id integer Required The id of the announcement the user has seen. Use the value returned by announcementsLatest.

Request Body

JSON
{
  "query": "announcementAck",
  "data": {
    "id": 12
  }
}

cURL Example

cURL
curl -X POST "https://api.virtualperformancetool.com/api" \
  -H "Content-Type: application/json" \
  -H "X-API-Version: 1.3.6" \
  -H "Authorization: Bearer <jwt>" \
  -d '{
    "query": "announcementAck",
    "data": { "id": 12 }
  }'

Response

JSON
{
  "apiVersion": "1.3.6",
  "success": true
}

Integration Tips

When to fetch

Fetch at app startup and optionally after login. Avoid aggressive polling.

Rendering strategy

Use summary for list cards, body for the detail modal/screen, and coverImageUrl as top media. Render galleryImages only when non-empty.

Body format handling

Respect bodyFormat. For markdown/html rendering, always sanitize before display. For plain text, preserve line breaks.

Detecting new announcements

Use the server-side seen flag — no local storage needed. The flag reflects the user's state across all their devices.

JavaScript
// 1. Fetch (JWT required)
const response = await fetch('https://api.virtualperformancetool.com/api', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Version': '1.3.6',
    'Authorization': `Bearer ${jwt}`
  },
  body: JSON.stringify({ query: 'announcementsLatest' })
});
const data = await response.json();

if (data.success && data.announcement && !data.announcement.seen) {
  showAnnouncement(data.announcement);
}

// 2. When the user dismisses/views the announcement:
await fetch('https://api.virtualperformancetool.com/api', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Version': '1.3.6',
    'Authorization': `Bearer ${jwt}`
  },
  body: JSON.stringify({
    query: 'announcementAck',
    data: { id: data.announcement.id }  // pass the id exactly as returned
  })
});