Build with ARA.

Challenge definitions for community tools, served through the Academy.

Start here

  1. Use this base URL:
    https://labs.almeidaracingacademy.com
  2. Read the integration guide and import OpenAPI into your API tooling.
  3. Run the reference client with Node.js 24 to try login and challenge reads.
  4. Implement the same flow in your overlay and match the returned car and track IDs to iRacing.

Desktop authentication

  1. Create a login transaction with a fresh S256 proof.
  2. Show the returned code in the app and open the browser login link.
  3. The member enters the code and signs in with the Academy.
  4. Poll every five seconds with your original proof to receive an ARA session token.

Send the token in Authorization: Bearer …. Sessions last 12 hours. Sign out with DELETE /api/v1/auth/session. No localhost callback, shared secret or refresh token is needed in your application.

See the step-by-step login contract for exact requests, responses and error handling.

Training plans

Regular and weekly challenges use the same collection and detail routes. Personal results and live iRacing telemetry are outside this API's scope.

MethodPathPurpose
GET
/api/v1/garage61/training-plans
List ARA training plans
GET
/api/v1/garage61/training-plans/{trainingPlanId}
Read challenges, targets and car/track mappings

Example authenticated request

curl 'https://labs.almeidaracingacademy.com/api/v1/garage61/training-plans?limit=100&offset=0' \
  -H "Authorization: Bearer $ARA_ACCESS_TOKEN"

Collection responses contain team, items, total, limit and offset. Follow pagination, then request each selected plan by ID. The OpenAPI specification contains full response examples.

Match the iRacing session

Polling and failures

Fetch on startup and at most once every five minutes while the app is in use. The protective limits are 120 requests per minute per IP and 60 per minute per user. Vercel also limits all API traffic to 240 per minute per IP per region before it reaches the service. These are not recommended polling rates.

Respect Retry-After on 429, or wait 60 seconds if absent. Edge errors may have a non-JSON body. Use bounded retries with jitter for temporary failures. Show cached data as stale when appropriate; do not treat failed requests as an empty challenge list.

See the error reference for status codes. A 503 indicates temporary unavailability, not an empty challenge list.

Read the integration guide