Skip to content

API Reference

Hails edited this page Jul 15, 2026 · 9 revisions

API Reference

hailsDotGO exposes a read-only JSON API for the game data it aggregates, a set of session-authenticated endpoints used by the site frontend, and a private API tier for trusted consumers. This page documents the endpoints, rate limits, and authentication rules. A live, always-current version of the public and private API tables is on the site itself: open https://pogo.hails.live/credits and switch to the API tab.

All endpoints are relative to the site root (for the production instance, https://pogo.hails.live). Errors are returned as JSON objects of the form {"error": "message"} with an appropriate HTTP status.

Public data endpoints

No authentication required. All responses carry Cache-Control: public, max-age=300.

Endpoint Method Returns Rate limit (per IP)
/api/data GET Combined bundle: Pokemon stats, moves, raids, Max Battles, shinies, shadow list, type chart, CP multipliers, types, localized names 10 per 2 minutes
/api/raids GET Current raid bosses grouped by tier ("1", "3", "5", "6" for Mega; Shadow bosses fold into their tier with a Shadow name prefix) 10 per 2 minutes
/api/maxbattles GET Current Max Battle bosses grouped by tier ("1", "2", "3") 10 per 2 minutes
/api/events GET Current and upcoming events (ScrapedDuck feed) 10 per 2 minutes
/api/events/{id} GET Sanitized HTML detail for one event; id must match ^[a-z0-9-]{1,128}$ 30 per 2 minutes
/api/pokemon GET Pokemon base stats 10 per 2 minutes
/api/moves GET {"fast": [...], "charged": [...]} move data 10 per 2 minutes

Bandwidth cap

On top of the request limits, the public data endpoints share a per-IP bandwidth budget: 15 MB per rolling 5-minute window, counted across all of the endpoints above. Exceeding it blocks the IP from these endpoints for 30 minutes and returns 429 with {"error":"bandwidth limit exceeded, try again later"}. Logged-in site users are unaffected because the frontend uses the session endpoint below.

Where the data comes from and how often it refreshes is documented in Data Sources.

Authenticated endpoints (session cookie)

These are the endpoints the site frontend uses. Authentication is the hgo_session cookie; there are no API keys. Mutating requests from a browser must also send the CSRF token in the X-CSRF-Token header (the token is rendered into every page; gorilla/csrf pairs it with the _pogo_csrf cookie). The PayPal webhook is the only CSRF-exempt route.

Endpoint Method Purpose
/api/app/data GET Same payload as /api/data, but session-authenticated and not subject to the public rate limits
/api/weather GET Current in-game weather and boosted types for the user's saved location (see Accounts and Roles)
/api/shinies GET The user's shiny collection
/api/shinies POST Add a shiny
/api/shinies/{id} PUT Update a shiny entry
/api/shinies/{id} DELETE Remove a shiny entry
/api/shinies/{id}/evolve POST Evolve a caught shiny: changes its pokemon_id to the target form and stamps evolved_at; body {"into": "PokemonName"}, plus an optional target region so regional evolution lines stay consistent

The shiny write endpoints (POST, PUT, and the public GET /api/shinies/of/{username} reader) carry a region field alongside the entry. The POST body fields are pokemon_id, form, region, method, costume, event_tag, and an optional caught_at date (YYYY-MM-DD). region is one of the four geographic forms (alolan, galarian, hisuian, paldean), one of the battle formes that reuse the same field (therian, origin, attack, defense, speed, sky), a Vivillon pattern code or Unown letter code for those species, or empty for the original form; any unrecognized value is rejected. It is kept separate from form so a regional or battle forme variant and a status such as Shadow can coexist on one entry. caught_at is accepted on both POST and PUT, validated to fall between Pokemon GO's launch (2016-07-06) and tomorrow; omitting it on an update leaves the stored date unchanged.

Social and feedback endpoints

See Social Features for the full behavioural description.

Endpoint Method Auth Purpose
/api/social/{username} GET session Relationship state: {is_self, is_friend, is_blocked, they_blocked_you}
/api/social/{username}/friend POST session + CSRF Add {username} as a friend
/api/social/{username}/friend DELETE session + CSRF Remove friend
/api/social/{username}/block POST session + CSRF Block {username}; removes friendship in both directions
/api/social/{username}/block DELETE session + CSRF Unblock
/api/notifications GET session Active raids (open, full, raiding) hosted by the caller's friends; used by the 🔔 badge poller and the /notifications page
/api/feedback/{username} GET none All feedback entries for {username} (public)
/api/feedback/{username} POST session + CSRF Submit or update your feedback; body {"option_id": N}
/api/feedback/entry/{id} DELETE session + CSRF Delete your own feedback entry
/api/users/search?q= GET session Search trainers by username or trainer name; returns [{username, trainer_name}]

Admin-only feedback option management (Admin role required):

Endpoint Method Purpose
/api/admin/feedback-options GET List all feedback options
/api/admin/feedback-options POST Create a new option
/api/admin/feedback-options/{id} PUT Update label, sentiment, sort order, or enabled state
/api/admin/feedback-options/{id} DELETE Delete an option

Admin-only sprite lock management (Admin role required):

Endpoint Method Purpose
/api/admin/sprite-locks GET List all trainer sprites with slug, label, group, and current min_rank
/api/admin/sprite-lock/{slug} POST Set min_rank for a sprite; body {"min_rank": N} where N is one of {0, 1, 2, 4, 5, 100}. Returns 400 if the sprite is a professor (auto-locked server-side)
/api/admin/sprite-lock/{slug} DELETE Remove the lock row, returning the sprite to rank 0 (unlocked)

Admin-only costume management (Admin role required). See the Admin Guide Costumes tab for the workflow:

Endpoint Method Purpose
/api/admin/costumes/name POST Give an unlabelled costume code a display label; lands in a server-side overlay so it is live in the picker immediately (add-only, cannot rename)
/api/admin/costumes/name DELETE Remove a label (un-name), refused when any saved user_shinies row uses that label
/api/admin/costumes/hide POST Dismiss a code the game flags as a costume but no trainer would record (e.g. the Gimmighoul coins)
/admin/check-costumes POST Read-only drift check: reports mined-asset costume codes not yet in the compiled catalog and the asset commit it was built from. Rate limited 5 per minute

The costumed sprites those labels resolve to are served by a public proxy:

Endpoint Method Purpose
/api/costume-sprite/{file} GET Serves a shiny costume sprite from the app's own origin (pulled from the mined-asset CDN once, cached, served immutably). Only filenames the catalog can produce are allowed

Bug and player report endpoints

Reporter and participant facing (writes also require CSRF). See Bug Reports and Player Reports.

Endpoint Method Auth Purpose
/api/bug-reports POST session File a bug report; body {subject, body}. Rate limited 6 per minute
/api/bug-reports GET session List the reports the caller participates in
/api/bug-reports/{id} GET session Full thread (internal notes only for staff)
/api/bug-reports/{id}/messages POST session Reply; staff may set visibility:"internal"
/api/bug-reports/{id}/invite POST session Invite a collaborator (reporter and collaborators up to 4; staff unlimited)
/api/bug-reports/{id}/status POST session Reporter resolve/reopen (staff get the full set)
/api/bug-reports/{id}/rating POST session Reporter CSAT `{rating:"good"
/api/player-reports POST session File a player report; body {username, reason, details}. Rate limited 6 per minute

Staff and admin management (Moderator role unless noted):

Endpoint Method Auth Purpose
/api/admin/bug-reports GET mod List all reports; filters status, label, `assignee=me
/api/admin/staff GET mod Active staff list (assignee dropdown and filter)
/api/admin/bug-reports/{id}/status POST mod Set status
/api/admin/bug-reports/{id}/priority POST mod Set priority (`low
/api/admin/bug-reports/{id}/assign POST mod Assign to a staff member (empty username unassigns)
/api/admin/bug-reports/{id}/labels POST mod Attach a label {label_id}
/api/admin/bug-reports/{id}/labels/{labelId} DELETE mod Detach a label
/api/admin/bug-reports/{id}/actioned POST mod Close a player report as actioned and thank the reporter
/api/admin/bug-report-labels GET mod List labels
/api/admin/bug-report-labels POST admin Create a custom label
/api/admin/bug-report-labels/{id} PUT / DELETE admin Update or delete a label (built-ins cannot be deleted)
/api/admin/bug-report-macros GET mod List canned responses
/api/admin/bug-report-macros POST admin Create a canned response
/api/admin/bug-report-macros/{id} PUT / DELETE admin Update or delete a canned response

Raid Finder endpoints

The full lobby lifecycle behind these is described in Raid Finder.

Endpoint Method Auth Purpose
/api/raid/overview GET none Public overview: per-boss open lobby and queue counts plus open custom lobbies (slow poll)
/api/raid/state GET session The caller's full raid state: queue position, lobby, deadlines, feedback owed (fast poll; doubles as the queue heartbeat)
/api/raid/queue POST session Join the matchmaking queue for a boss
/api/raid/queue DELETE session Leave the queue
/api/raid/lobbies POST session Create a lobby (host)
/api/raid/lobbies/{id} DELETE session Cancel a lobby (host or staff)
/api/raid/lobbies/{id}/confirm POST session Member confirms within the confirm window
/api/raid/lobbies/{id}/leave POST session Member leaves the lobby
/api/raid/lobbies/{id}/kick POST session Host or staff removes a member
/api/raid/lobbies/{id}/invited POST session Host confirms in-game invites were sent
/api/raid/lobbies/{id}/report POST session Host's post-raid attendance report
/api/raid/lobbies/{id}/feedback POST session Member's post-raid feedback (raid success, commend or dislike)

Awards endpoints

See Trust and Awards for granting rules.

Endpoint Method Auth Purpose
/api/awards GET none Active award catalog
/api/awards/of/{username} GET none Awards a user has received
/api/awards/{id}/grant POST session Grant an award by username (staff always; community granting behind a feature flag plus a minimum trust score)
/api/shinies/of/{username} GET none A user's public shiny collection; includes sprite_url (shiny variant, pre-resolved). Returns [] when the user does not exist, has a private profile, or has enabled Hide shiny collection in Settings

IV Calculator endpoints

See IV Calculator for the user-facing description.

Endpoint Method Auth Purpose
/api/iv/calculate POST none Enumerate all matching IV spreads. Body: {pokemon_name, cp, hp, dust_cost, trainer_level, top_stat, appraisal_bars}. Returns {candidates, count, definitive, pokemon}
/api/iv/ocr POST session Upload a screenshot (multipart image field, JPEG/PNG) and receive the same response shape as /api/iv/calculate after OCR extraction. Rate-limited to 10 per minute per IP
/api/iv/pokemon GET session Paginated Pokémon box: ?limit=N&offset=N. Returns {pokemon: [...], total}

The OCR response carries several extra fields on top of the shared calculate shape:

  • arc_level: the level read from the level arc (when the arc scan succeeds, cp_source is reported as arc-level).
  • best_buddy_assumed: set when the CP was interpreted as a best-buddy boosted value.
  • arc_rescue: set when the arc reading rescued a spread the CP alone could not pin down.
  • iv_summary: the min and max IV percent across the returned candidates.
  • truncated_from: present when the candidate list was capped, giving the pre-cap count.
  • species_candidates: present when the species is ambiguous, listing the plausible matches.
  • name_source: how the species was identified, now including candy (read from the candy line, for nicknamed Pokemon) and fulltext. | /api/iv/pokemon | POST | session + CSRF | Save a Pokémon to the box. Returns HTTP 409 when the 3000-entry limit is reached | | /api/iv/pokemon/{id} | DELETE | session + CSRF | Remove a box entry by ID |

Private API

The private tier mirrors the public data endpoints without the public rate limits and bandwidth cap, and adds a refresh trigger. It requires the api_access account flag, which only the superadmin can grant and which only takes effect on admin accounts (the superadmin always has access). Requests still authenticate with the session cookie. Contact the site operator to request access.

Endpoint Method Notes
/api/private/data GET Mirror of /api/data
/api/private/raids GET Mirror of /api/raids
/api/private/maxbattles GET Mirror of /api/maxbattles
/api/private/events GET Mirror of /api/events
/api/private/events/{id} GET Mirror of /api/events/{id}
/api/private/pokemon GET Mirror of /api/pokemon
/api/private/moves GET Mirror of /api/moves
/api/refresh POST Triggers an immediate background re-fetch of all PoGoAPI data; globally limited to 2 requests per 10 minutes across all callers

Mobile API (/api/mobile/v1)

The mobile companion app uses a versioned prefix so the routes remain stable as the main web API evolves. All /api/mobile/v1/* routes are CSRF-exempt (mobile clients cannot set _pogo_csrf cookies). Authentication uses Bearer tokens:

Authorization: Bearer <session_token>

The session token is the same value used by the web cookie (hgo_session); it is returned by /api/mobile/v1/auth/login and remains valid until the user logs out or the token expires (30-day rolling TTL).

Authentication

Endpoint Method Auth Purpose
/api/mobile/v1/auth/login POST none Exchange {username, password} for a session token. Rate-limited to 5 per minute per IP. Returns {token, user}
/api/mobile/v1/auth/session DELETE Bearer Log out and invalidate the token
/api/mobile/v1/auth/me GET Bearer Current user profile including trainer_level
/api/mobile/v1/profile PUT Bearer Update trainer name, code, level, avatar, pronouns, location fields

Push notifications

Endpoint Method Auth Purpose
/api/mobile/v1/push/token POST Bearer Register a device push token. Body: {token, platform, device_name} where platform is "android" or "ios"
/api/mobile/v1/push/token DELETE Bearer Unregister the device push token

Push notifications are sent by the server for raid events (match found, host kicked you, lobby cancelled, 30-second confirm warning). Android uses FCM; iOS uses APNs. Both are silently disabled when the required environment variables are absent. See Configuration for the env var names.

Game data aliases

Stable versioned mirrors of the public data endpoints, same responses, same cache headers, no rate limits for authenticated clients.

Endpoint Method Purpose
/api/mobile/v1/pokemon GET Pokémon base stats
/api/mobile/v1/raids GET Current raid bosses
/api/mobile/v1/events GET Current and upcoming events
/api/mobile/v1/data GET Full data bundle
/api/mobile/v1/raid/overview GET Per-boss lobby and queue counts (public)

Shiny Collection (mobile)

The same collection as the web /api/shinies endpoints, under the versioned path. Every entry the app receives carries a server-resolved sprite_url (costume, regional, or base variant) so the app never duplicates the sprite tables.

Endpoint Method Purpose
/api/mobile/v1/shinies GET List the caller's collection, each entry with sprite_url
/api/mobile/v1/shinies POST Add a catch; returns {id, sprite_url} for immediate render
/api/mobile/v1/shinies/{id} PUT Update an entry (shared with the web handler)
/api/mobile/v1/shinies/{id} DELETE Remove an entry
/api/mobile/v1/shinies/{id}/evolve POST Evolve a caught shiny (accepts the target region)
/api/mobile/v1/shinies/reference GET The region and catch-method choices with translated labels, so the app's pickers track the site without an app update

IV Calculator (mobile)

Same logic as the web IV endpoints under a versioned path:

Endpoint Method Purpose
/api/mobile/v1/iv/calculate POST Find IV candidates
/api/mobile/v1/iv/ocr POST Screenshot OCR; 10 per minute per IP
/api/mobile/v1/iv/pokemon GET Paginated Pokémon box
/api/mobile/v1/iv/pokemon POST Save a Pokémon to box
/api/mobile/v1/iv/pokemon/{id} DELETE Remove a box entry

Raid Finder (mobile)

Same logic as the web raid endpoints; see Raid Finder for the state machine.

Endpoint Method Purpose
/api/mobile/v1/raid/state GET Caller's full raid state (queue + lobby)
/api/mobile/v1/raid/queue POST Join the matchmaking queue
/api/mobile/v1/raid/queue DELETE Leave the queue
/api/mobile/v1/raid/lobbies POST Create a lobby
/api/mobile/v1/raid/lobbies/{id} DELETE Cancel a lobby
/api/mobile/v1/raid/lobbies/{id}/confirm POST Confirm within the confirm window
/api/mobile/v1/raid/lobbies/{id}/leave POST Leave the lobby
/api/mobile/v1/raid/lobbies/{id}/kick POST Host removes a member
/api/mobile/v1/raid/lobbies/{id}/invited POST Host confirms in-game invites were sent
/api/mobile/v1/raid/lobbies/{id}/report POST Host's post-raid attendance report
/api/mobile/v1/raid/lobbies/{id}/feedback POST Member's post-raid feedback

Webhook

Endpoint Method Notes
/api/store/webhook POST PayPal server-to-server webhook (CHECKOUT.ORDER.APPROVED). CSRF-exempt; authenticity is checked by verifying the transmission signature against PAYPAL_WEBHOOK_ID through PayPal's verification API. Always answers 200 so PayPal does not retry. See Store.

Auth and admin routes

Login, registration, settings, translation, and the admin toolset are session-flow routes rather than a stable API surface and are intentionally not exhaustively documented here. The login endpoint is limited to 10 attempts per minute per IP and registration to 5 per minute per IP. For the full admin route set and the role each action requires, see the Admin Guide; for the translation endpoints see Translator Workspace.

Clone this wiki locally