Admin API

Lexicons

Manage lexicons and network lexicons. See the Lexicons guide for background on how lexicons drive indexing and XRPC routing.

const TOKEN = "hv_..."; // your API key
const headers = { Authorization: `Bearer ${TOKEN}` };

Upload / upsert a lexicon

POST /admin/lexicons
interface LexiconResult {
  id: string;
  revision: number;
}

const response = await fetch("http://127.0.0.1:3000/admin/lexicons", {
  method: "POST",
  headers: {
    ...headers,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    lexicon_json: {
      lexicon: 1,
      id: "xyz.statusphere.status",
      defs: {
        main: {
          type: "record",
          key: "tid",
          record: {
            type: "object",
            required: ["status", "createdAt"],
            properties: {
              status: { type: "string", maxGraphemes: 1 },
              createdAt: { type: "string", format: "datetime" },
            },
          },
        },
      },
    },
    backfill: true,
    target_collection: null,
  }),
});
const data: LexiconResult = await response.json();
FieldTypeRequiredDescription
lexicon_jsonobjectyesRaw lexicon JSON (must have lexicon: 1 and id)
backfillbooleannoWhether uploading triggers historical backfill (default true)
target_collectionstringnoFor query/procedure lexicons, the record collection they operate on
scriptstringnoLua script for query/procedure endpoints
index_hookstringnoIndex hook Lua script for record lexicons

Response: 201 Created (new) or 200 OK (upsert)

{
  "id": "xyz.statusphere.status",
  "revision": 1
}

List lexicons

GET /admin/lexicons
interface Lexicon {
  id: string;
  revision: number;
  lexicon_type: string;
  backfill: boolean;
  created_at: string;
  updated_at: string;
}

const response = await fetch("http://127.0.0.1:3000/admin/lexicons", {
  headers,
});
const data: Lexicon[] = await response.json();

Response: 200 OK

[
  {
    "id": "xyz.statusphere.status",
    "revision": 1,
    "lexicon_type": "record",
    "backfill": true,
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z"
  }
]

Get a lexicon

GET /admin/lexicons/{id}
const response = await fetch(
  "http://127.0.0.1:3000/admin/lexicons/xyz.statusphere.status",
  { headers },
);
const data = await response.json();

Response: 200 OK with full lexicon details including raw JSON.

Delete a lexicon

DELETE /admin/lexicons/{id}
const response = await fetch(
  "http://127.0.0.1:3000/admin/lexicons/xyz.statusphere.status",
  {
    method: "DELETE",
    headers,
  },
);

Response: 204 No Content

Network Lexicons

Network lexicons are fetched from the atproto network via DNS TXT resolution and kept updated via the Jetstream subscription. See Lexicons - Network lexicons for background.

Add a network lexicon

POST /admin/network-lexicons
interface NetworkLexiconResult {
  nsid: string;
  authority_did: string;
  revision: number;
}

const response = await fetch("http://127.0.0.1:3000/admin/network-lexicons", {
  method: "POST",
  headers: {
    ...headers,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    nsid: "xyz.statusphere.status",
    target_collection: null,
  }),
});
const data: NetworkLexiconResult = await response.json();
FieldTypeRequiredDescription
nsidstringyesThe NSID of the lexicon to watch
target_collectionstringnoFor query/procedure lexicons, the record collection they operate on

HappyView resolves the NSID authority via DNS TXT, fetches the lexicon from the authority's PDS, parses it, and stores it.

Response: 201 Created

{
  "nsid": "xyz.statusphere.status",
  "authority_did": "did:plc:authority",
  "revision": 1
}

List network lexicons

GET /admin/network-lexicons
interface NetworkLexicon {
  nsid: string;
  authority_did: string;
  target_collection: string | null;
  last_fetched_at: string;
  created_at: string;
}

const response = await fetch("http://127.0.0.1:3000/admin/network-lexicons", {
  headers,
});
const data: NetworkLexicon[] = await response.json();

Response: 200 OK

[
  {
    "nsid": "xyz.statusphere.status",
    "authority_did": "did:plc:authority",
    "target_collection": null,
    "last_fetched_at": "2025-01-01T00:00:00Z",
    "created_at": "2025-01-01T00:00:00Z"
  }
]

Remove a network lexicon

DELETE /admin/network-lexicons/{nsid}
const response = await fetch(
  "http://127.0.0.1:3000/admin/network-lexicons/xyz.statusphere.status",
  {
    method: "DELETE",
    headers,
  },
);

Removes the network lexicon tracking and also deletes the lexicon from the lexicons table and in-memory registry.

Response: 204 No Content