Zones API

The Zones API lets you create, manage, and query zones within The Grid. All endpoints are served from https://api.a-new-world.com/api/zones. Endpoints require authentication unless noted otherwise.

Zone Discovery

List Zones

GET /api/zones?page=1&limit=20&search=mall&size_tier=district&sort=visit_count

Returns a paginated list of public, active zones.

Query Parameters:

ParamTypeDefaultDescription
searchstringSearch zones by name or description
size_tierstringFilter by plot, district, region, realm
sortstringvisit_countvisit_count, created_at, name, rating_sum
pagenumber1Page number
limitnumber20Results per page (max: 50)

Response:

{
  "zones": [...],
  "pagination": { "page": 1, "limit": 20, "total": 342, "pages": 18 }
}

Featured Zones

GET /api/zones/featured

Returns developer-curated featured zones (up to 20). Rotates weekly.

Trending Zones

GET /api/zones/trending?period=week

Zones ranked by recent visitor count. period: day, week (default), month.

Nearby Zones

GET /api/zones/nearby?x=5&y=-3&radius=10

Returns zones within a coordinate radius (max radius: 100). Sorted by distance.


Zone CRUD

Get Zone

GET /api/zones/:id

Returns full zone details including settings and metadata. No auth required.

Create Zone ✅ Auth

POST /api/zones

Purchase and create a new zone. Credits are deducted atomically.

Request Body:

{
  "name": "Crystal Mall",
  "description": "A sprawling shopping center",
  "size_tier": "district",
  "coord_x": 5,
  "coord_y": -3,
  "visibility": "public",
  "theme": "shopping"
}

Tier Pricing:

TierDimensionsCost
plot64×64×64100 credits
district256×256×128500 credits
region1024×1024×2562,500 credits
realm4096×4096×51210,000 credits

Validation:

Errors: 400 (validation), 402 (insufficient credits), 409 (coordinates occupied)

Update Zone ✅ Auth (Owner Only)

PATCH /api/zones/:id

Update zone metadata. Supports partial updates.

Fields: name, description, visibility, theme, max_players, settings

Archive Zone ✅ Auth (Owner Only)

DELETE /api/zones/:id

Soft-deletes the zone (sets status to archived). The Nexus cannot be deleted.


Zone Connection

Join Zone ✅ Auth

GET /api/zones/:id/join

Validates access and returns dedicated server connection info. This is the entry point for connecting to a zone's multiplayer session.

Access checks (single consolidated query):

  1. Zone exists and is active
  2. Player is not banned
  3. Player has access (public = open, private/invite-only = membership or ownership required)

Response (dedicated server available):

{
  "zone_id": "zone_abc123",
  "server_host": "192.168.1.100",
  "server_port": 7777,
  "visit_token": "eyJ...",
  "player_count": 12,
  "max_players": 50
}

The client uses server_host:server_port to travel to the UE5 dedicated server, passing the visit_token as a URL parameter.

Response (no server available):

{ "error": "No active server for this zone" }

Errors: 404 (inactive/missing), 403 (banned/denied), 503 (no server available)


Zone Blocks

Get Blocks (Chunked)

GET /api/zones/:id/blocks?chunk_x=0&chunk_y=0&chunk_z=0

Returns all blocks within a 32×32×32 chunk. Used for proximity-based block streaming.

Response:

{
  "chunk": { "x": 0, "y": 0, "z": 0 },
  "blocks": [
    {
      "id": "block_abc",
      "x": 5, "y": 10, "z": 0,
      "block_type": "cube",
      "asset_id": "asset_tex001",
      "rotation": 0,
      "scale_x": 1, "scale_y": 1, "scale_z": 1,
      "placed_by": "user_xyz",
      "metadata": null
    }
  ]
}

Note: Real-time block operations (place/remove) are handled via UE5 dedicated server RPCs. The REST endpoint is for initial loading and streaming.


Zone Members & Roles ✅ Auth

List Roles

GET /api/zones/:zoneId/roles

Create Role (Admin+)

POST /api/zones/:zoneId/roles
{
  "name": "Shop Staff",
  "color": "#e67e22",
  "permissions": ["subzone.build", "subzone.assets", "chat.moderate"],
  "priority": 5
}

Delete Role (Admin+)

DELETE /api/zones/:zoneId/roles/:roleId

Removes the role and all member assignments with that role.

List Members

GET /api/zones/:zoneId/members

Returns members with their usernames, avatars, and assigned role names.

Assign Role

POST /api/zones/:zoneId/members
{ "user_id": "user_abc", "role_id": "role_builder" }

Assigns a role to a member in this zone.

Remove Member

DELETE /api/zones/:zoneId/members/:userId

Zone Bans ✅ Auth (Admin+)

List Bans

GET /api/zones/:zoneId/bans

Ban Player

POST /api/zones/:zoneId/bans
{
  "user_id": "user_xyz",
  "reason": "Griefing",
  "duration_hours": 24
}

Omit duration_hours for a permanent ban. Zone owners cannot be banned.

Unban Player

DELETE /api/zones/:zoneId/bans/:userId

Sub-Zones ✅ Auth

List Sub-Zones

GET /api/zones/:zoneId/sub-zones

Create Sub-Zone (Owner Only)

POST /api/zones/:zoneId/sub-zones
{
  "name": "Store A1",
  "bounds_min": [10, 0, 10],
  "bounds_max": [30, 16, 30],
  "rent_price": 100,
  "rent_cycle": "monthly",
  "max_blocks": 5000
}

Validation:

Lease Sub-Zone

POST /api/zones/:zoneId/sub-zones/:subId/lease

Rents a sub-zone. Credits are deducted immediately for the first billing cycle. 95% goes to the zone owner, 5% platform commission. Rent renews automatically via daily cron — see rent collection.

Delete Sub-Zone (Owner Only)

DELETE /api/zones/:zoneId/sub-zones/:subId

Portals ✅ Auth

List Portals

GET /api/zones/:zoneId/portals

Create Portal (Owner or zone.portals permission)

POST /api/zones/:zoneId/portals
{
  "target_zone_id": "zone_xyz",
  "source_x": 10, "source_y": 0, "source_z": 5,
  "target_x": 0, "target_y": 0, "target_z": 5,
  "name": "To Market Square",
  "bidirectional": true
}

If bidirectional is true, a reverse portal is automatically created in the target zone.

Delete Portal

DELETE /api/zones/:zoneId/portals/:portalId

Credits

Get Balance ✅ Auth

GET /api/credits
{
  "balance": 4350,
  "lifetime_earned": 12000,
  "lifetime_spent": 7650
}

Transaction History ✅ Auth

GET /api/credits/transactions?page=1&limit=50

Purchase Credits ✅ Auth

POST /api/credits/purchase
{ "pack": "creator" }

Returns a Stripe Checkout Session URL.


Error Codes

All errors follow the format { "error": "message" } with the appropriate HTTP status code.

CodeMeaning
400Validation error (bad input)
401Missing or invalid JWT
402Insufficient credits
403Access denied (not owner, banned, insufficient permissions)
404Resource not found or inactive
409Conflict (coordinates occupied, already connected, sub-zone overlap)
503Zone is full (player capacity reached)