Skip to content

HTTP & external backends

HTTP.* lets your world call an approved backend provider from server scripts — most usefully your own database for things that must survive a restart: player profiles, progression, leaderboards, rewards. (For "this session" state, use Storage — it's faster and needs no backend.)

HTTP runs server‑side only, so endpoints and keys are used on the server, never shipped to players.

Only approved providers can be reached

Outbound HTTP is allow‑listed. Your scripts can reach only the providers below — not an arbitrary third‑party API, not a custom domain or IP you type in, and not the local machine or your own server. Any other destination is refused with a 403 before the request is sent. This is enforced on the server and cannot be turned off by a world.

Approved providers

Provider Main use cases Auth type Base URL example Notes / best practices
Supabase Postgres DB, Auth, Storage, Realtime supabase (preferred) https://your-project.supabase.co Strong Row Level Security (RLS). Top recommendation.
Firebase (Google) Realtime Database, Auth, Storage, Functions bearer https://your-project.firebaseio.com (or project‑specific) Generous free tier; excellent for realtime features.
PlayFab (Microsoft) Game backend (leaderboards, economy, player data) bearer or apikey https://titleId.playfabapi.com Built specifically for games. Key player data by their stable account idPlayer.GetUserId(id).
Nhost Postgres + GraphQL bearer https://your-subdomain.nhost.run Good Supabase alternative with GraphQL support.
Neon Serverless Postgres bearer (or key via HTTP.Secret) https://your-project.neon.tech Modern Postgres with branching. Database‑focused.

Reachable hosts are the providers' own domains — *.supabase.co, *.firebaseio.com / *.firebasedatabase.app / *.cloudfunctions.net, *.playfabapi.com, *.nhost.run, *.neon.tech. The Auth type column maps to a scheme in the Provider Manager (below).

1. Store a credential (Provider Manager)

Open Window ▸ Social Scape ▸ Provider Manager, Add a provider with Type = HTTP (credential):

Field Meaning
Handle A name your scripts reference, e.g. my-db.
Base URL The API root — must be one of the approved providers above, e.g. https://YOUR-PROJECT.supabase.co.
Auth How the key is attached (see the table below).
API Key Stored encrypted on your account; never displayed again.

Never put an API key in a script

World bundles aren't encrypted — anything in a script is readable by others. So you don't paste keys into headers. Instead you store the key in the Provider Manager (encrypted on your account) and reference it by handle; the server injects the key at request time. Keys never travel in your world.

Auth schemes

Scheme What it sends Use for
bearer Authorization: Bearer <key> most REST APIs — Firebase, PlayFab, Nhost, Neon
apikey apikey: <key> services using an apikey header
supabase both apikey: <key> and Authorization: Bearer <key> — the same key Supabase (it wants both; one key is correct)
header <YourHeaderName>: <key> a single custom header, e.g. X-Api-Key (PlayFab title key)
none nothing — you place the key yourself anything unusual (below)

Supabase uses one key in two headers

Supabase's server pattern puts the same anon/service key in both apikey and Authorization: Bearer. So you only enter one key — supabase auth sends it to both. (Want a different Authorization value, like a user JWT? Use none + HTTP.Secret, below.)

2a. Call it by handle — HTTP.*Via

The server resolves the handle → base URL + auth, prepends the base URL to your path, and sends. Your script never sees the key or the URL:

using System.Collections;
using UnityEngine;
using NexusVM.Unity;

class Leaderboard : NexusBehaviour
{
    IEnumerator SaveScore(string accountId, int score)
    {
        string body = "{\"user_id\": \"" + accountId + "\", \"score\": " + score + "}";
        var result = HTTP.PostVia("my-db", "/rest/v1/scores", body);
        yield return result;                       // wait for the request

        if (result.Success) Debug.Log("Saved: " + result.Body);
        else                Debug.LogError("Failed (" + result.StatusCode + "): " + result.Error);
    }
}
Method Signature
GET HTTP.GetVia(handle, path[, headers])
POST/PUT/PATCH HTTP.PostVia/PutVia/PatchVia(handle, path, body[, headers])
DELETE HTTP.DeleteVia(handle, path[, headers])

2b. Reference just the secret — HTTP.Secret

For a provider whose auth the schemes don't cover (a key in the query string, a user JWT, two separate keys), keep the full‑URL call and drop the key into a header with HTTP.Secret(handle). It returns an opaque reference; the real key is substituted server‑side at send‑time and is never readable in your script:

var headers = new Dictionary<string, string>();
headers["Authorization"] = "Bearer " + HTTP.Secret("my-neon-key");

// The URL must still be an approved provider host (here, Neon):
var result = HTTP.Get("https://your-project.neon.tech/sql", headers);
yield return result;

Raw calls (HTTP.Get(url) …)

HTTP.Get/Post/Put/Patch/Delete(url[, body][, headers]) take a full URL — but that URL must still be an approved provider (the same allow‑list applies). There is no way to reach an arbitrary or public URL; use *Via for anything that needs a stored key.

Reading the result

Every call returns an HTTPAsyncResult you yield return, then read:

Success (bool) · StatusCode (int) · Body (response string) · Error (string).

Letting an NPC answer from a request

Calling HTTP from inside an NPC action? Mark the action Async so the NPC waits for the result and speaks it in one turn (e.g. "what's my score?"). See Custom actions ▸ Async actions.

Examples by provider

Store an HTTP credential (handle my-db) with the provider's base URL + auth, then:

// Supabase (auth: supabase) — PostgREST
HTTP.GetVia ("my-db", "/rest/v1/profiles?user_id=eq." + accountId);
HTTP.PostVia("my-db", "/rest/v1/profiles", json);

// Firebase Realtime DB (auth: bearer) — REST is path + ".json"
HTTP.GetVia ("my-db", "/scores/" + accountId + ".json");
HTTP.PutVia ("my-db", "/scores/" + accountId + ".json", json);

// PlayFab (auth: header, X-SecretKey) — server API
HTTP.PostVia("my-db", "/Server/UpdatePlayerStatistics", json);

// Nhost (auth: bearer) — GraphQL
HTTP.PostVia("my-db", "/v1/graphql", "{\"query\":\"{ scores { user_id score } }\"}");

// Neon (auth: bearer) — serverless SQL over HTTP
HTTP.PostVia("my-db", "/sql", "{\"query\":\"select score from scores where user_id = $1\",\"params\":[\"" + accountId + "\"]}");

Always key durable records by the player's stable account id (Player.GetUserId(id)) — not by Player.IdOf / Networking.GetPlayers, which return a per‑session id that changes on reconnect. (Tip: scope your database with Row Level Security / permissions — defence in depth.)

Usage guidelines

  • Only the approved providers above can be reached, via the Provider Manager. Arbitrary URLs, custom hosts/IPs, and the local machine are blocked.
  • Always use credential handles (*Via / HTTP.Secret) — never paste a raw API key into a script.
  • Enable Row Level Security / permissions on your backend where possible.
  • All calls are server‑side only — they don't run in the offline tester, and clients never see your endpoints or keys.

When to use what

Need Use
Counter/flag for the current session Storage
Data that survives restarts (profiles, leaderboards) HTTP → an approved provider (via a credential)
A provider needing a key a Provider Manager HTTP credential + *Via / HTTP.Secret