MAPPLS REALVERSE / DEVELOPERS
Real places. Interactive experiences.

Bring the world
into your application.

Embed a navigable 3D world, take visitors through a heritage circuit, or build your own experience using geospatial scenarios, places and avatars.

Request developer access →Check an existing request

Explore & discover

Versioned REST APIs for scenario metadata, WGS84 places and curated tourism circuits.

Embed & interact

A responsive iframe widget and web component with fly-to, place visits, avatar placement and selection events.

Build with control

Scoped keys, unrestricted integration domains, short-lived viewer sessions and administrator-managed usage limits.

Domain restrictions are temporarily disabled. Existing and new developer keys and viewer sessions work from any domain. No domain registration is required; API keys, scopes, quotas and expiry still apply.

01 / Integrate

A server key. A browser session.

Apply below, save your request receipt, and return here after your administrator reviews the request. Retrieve the approved key once and store it in a server secret. Your backend creates a short-lived session for your application; the browser receives only that session URL.

1. Your server · Node.js / ESM

2. Your application · JavaScript

The container controls the widget’s size. Give it a height; the viewer fills its width and height and supports touch, trackpad navigation and fullscreen. On expiry, request a fresh session through your backend and replace the widget. Authenticate and rate-limit that endpoint for your own users.

Or use a web component

React, Vue and other frameworks can mount RealverseWidget into a container and call dispose() on unmount. Native applications may embed the same application page in a web view, or call the REST API from their backend. Never distribute a server key in a mobile binary.

02 / Reference

API v1 & SDK downloads

Method & endpointScopeResult
GET /api/v1/scenariosscenarios:readTourism, civil and industrial catalogue
GET /api/v1/scenarios/{id}scenarios:readManifest, extent, provenance and map URL
GET /api/v1/scenarios/{id}/placesplaces:readStable IDs, place URLs, embed options and source references
GET /api/v1/scenarios/{id}/places/{placeId}places:readOne place, permanent URL and embed options
GET /api/v1/scenarios/{id}/toursplaces:readOrdered sightseeing stops
POST /api/v1/embed-sessionsembed:createViewer URL, origin and expiry

Send Authorization: Bearer rv_sk_… over HTTPS. Default policy: 60 requests/minute, 10,000/day, 90-day key validity; your admin may change these. Quotas use UTC days and fixed minute windows. Limits appear in X-RateLimit-Limit and X-RateLimit-Daily-Limit. HTTP 400 means invalid input, 401 invalid/expired key, 403 missing scope (or unapproved origin when domain restrictions are enabled), 404 unknown resource, 409 conflict, 429 quota exceeded. Back off on 429; do not retry mutations blindly.

Widget commands & events
await widget.ready;
await widget.flyTo({ lat:26.8712, lon:80.9122, height:800 });
await widget.visitPlace('rumi-darwaza', { avatar:true });
await widget.placeAvatars({ lat:26.8708, lon:80.9122 });
await widget.setCameraMode('follow');
const state = await widget.getState();
widget.addEventListener('placeSelected', event => console.log(event.detail));
widget.addEventListener('cameraChanged', event => console.log(event.detail));
widget.addEventListener('error', event => console.log(event.detail));
// On removal:
widget.dispose();

Camera modes: free, first, follow, front, shoulder, orbit, bird. Place IDs come from the places API. The widget state includes the last visited place ID and its permanent placeURL. Coordinates are WGS84 degrees; height is metres. Displayed altitude follows the selected terrain source and is not guaranteed to be survey height. Commands use validated postMessage messages with parent-window checks; the handshake binds replies to the actual embedding page.

Sessions, security & data rights

Sessions last 60–3,600 seconds (default 900), currently work on any integration domain, and expire no later than the key. Keep their URLs private. Revocation blocks new sessions immediately; active viewers revalidate at most every 60 seconds. Creating a new session selects the initial scenario; users may explore the public globe and other public scenarios. Protected exercise rooms and private admin data are outside this API.

API quota counts API requests, not individual map tiles. The usage dashboard reports authenticated API calls; it is not a billing system or visitor analytics service. Data source licences continue to apply: retain attribution and observe ODbL requirements for OSM-derived data. Landmark reconstructions and illustrative assets are distinguished in manifests. Private data import, user authentication, payments, bookings and turn-by-turn routing are not part of this developer API.

Python quickstart
import os
from realverse import RealverseClient
client = RealverseClient(os.environ['REALVERSE_BASE_URL'],
                         os.environ['REALVERSE_API_KEY'])
print(client.list_places('prayagraj-tourism'))
session = client.create_embed_session('prayagraj-tourism',
                                      'https://your-app.example',
                                      place='triveni-sangam')
# Return session['url'] to your authenticated frontend.

3D models & rich place content

Each place supports modelAssets and richContent through the same versioned CRUD and moderation API. In Content studio, edit model position, rotation, scale, visibility and colour; replace/upload self-contained GLB models; add text, images, video, audio and links.

const file = await client.uploadMedia(scenario, "landmark.glb", bytes);
await client.updatePlace(scenario, place.id, {
  modelAssets: [{id:"landmark", mediaId:file.id, scale:[1,1,1]}],
  richContent: {sections:[{title:"About", body:"Place story"}], media:[]}
}, {expectedVersion:place.contentVersion, note:"Updated model and story"});

GET /api/v1/scenarios/{scenario}/media lists models/uploads. POST raw bytes to that path with ?filename=.... DELETE /media/{id} removes unused uploads. Read requires places:read; upload/delete requires places:write. Uploads are private until a referring place revision is published. 16 MiB/file, 256 MiB managed storage. HTTPS image/video/audio links are also supported. Models use radians for rotation, Blender X/Y/Z scale and terrain-relative altitudeOffset. Empty model/media arrays remove attachments; omitted fields retain them. Published files retained in history remain available for restoration.

Contribute / manage / moderate

Place content is a shared, versioned catalogue.

Open Content studio to view every attribute, create or edit places, import JSON / GeoJSON, review contributions and configure contributor policies. Existing scenario places are seeded once into the database; edits survive restarts and deployments. Published content is shared by SaaS, native web views, SDK reads and embedded viewers. Reload a scenario or choose Refresh places to see newly published changes.

EndpointScopePurpose
POST /api/v1/scenarios/{id}/placesplaces:writeCreate a contribution; {place, expectedVersion:0, note}
PATCH /api/v1/scenarios/{id}/places/{placeId}places:writeShallow attribute patch; {place, expectedVersion, note}
DELETE /api/v1/scenarios/{id}/places/{placeId}places:writeReversible removal; {expectedVersion, note}
POST /api/v1/scenarios/{id}/importplaces:write{places:[…], note} or {geojson:FeatureCollection, note}; atomic batch
GET /api/v1/contributionsplaces:writeOwn history; authorized reviewers also see their permitted areas
POST /api/v1/contributions/{id}/reviewplaces:moderate{action:'approve'|'reject', note}; additional moderator policy required

Publishing and permissions

Write access never comes with a read key or an embed session. Request places:write and have an administrator approve it. Default workflow is approval required: pending proposals do not alter any public place. An administrator can grant automatic publishing per contributor, restrict their scenarios, block access or grant moderation. Developer policies attach to the application and survive key rotation. Moderator keys need both places:write (queue reads) and places:moderate (decisions), plus an explicit moderation policy. A non-admin cannot approve their own submission.

Mutations return a contribution with status pending or published (HTTP 202), not a promise of publication. Read contentVersion before updates or deletion and submit it as expectedVersion. A stale version returns 409. Pending approvals also check the version. Rejecting a published revision restores its previous state, including deleted places, only when it remains the latest revision; otherwise edit the current place. IDs of removed places remain reserved. Rejected submissions can be revised and resubmitted as a new contribution. Decisions, actors and timestamps remain in history.

Place data contract

Required: id (lowercase letters, digits and hyphens; max 160), name (max 200), lat (−90…90) and lon (−180…180), both WGS84 decimal degrees. Existing attributes are preserved: category, description, kind, sourceFeature, sourceURL, geometryAccuracy, modelAccuracy, arrival, and custom JSON metadata. Source links must use HTTP(S). Include attribution, licence and provenance for new content. height is camera viewing height in metres; use a separate altitude and altitudeDatum for measured elevation. contentVersion is server-managed. Patches merge top-level fields; nested objects replace the previous object. Place updates do not regenerate 3D meshes, terrain, roads or building datasets; use Data admin for those.

Maximum 250,000 characters per place, nesting depth 16, 100 records per atomic import, 256 KiB per developer API request (split larger batches); studio uploads allow 3 MB. GeoJSON imports accept Point features only, with feature.id or properties.id and properties.name. For existing IDs, supply contentVersion from an export. Contributions support scenario, status and offset filters, return at most 100 records and nextOffset. API quotas and existing domain policy still apply. Source metadata is contributor-supplied; review it before publishing. Use Places & community for guest contributions or self-service sign-up; administrators can also manage users in Administration. No automatic contributor email notifications are sent.

Server SDK example

const existing = await client.getPlace('lucknow-tourism', 'rumi-darwaza');
const contribution = await client.updatePlace('lucknow-tourism', existing.id,
  { description: 'Updated visitor information',
    sourceURL: 'https://your-source.example/record' },
  { expectedVersion: existing.contentVersion, note: 'Checked against source' });
// Show pending / published in your UI.
const queue = await client.listContributions({ status: 'pending' });
// Only on your authenticated moderator route, with approved moderator permissions:
await client.reviewContribution(contribution.id,
  { action: 'approve', note: 'Source and coordinates checked' });

CRUD from a widget

Supply a content adapter that calls your own authenticated server. That server uses RealverseClient, validates the caller’s identity, allowed operations and scenario, and applies CSRF protection and rate limits. A server API key represents your whole application; a caller-supplied author field does not establish identity. Use separate developer applications/policies for different trust levels. Never expose a write or moderation key in a browser, iframe or mobile app.

const widget = new RealverseWidget(container, {
  sessionUrl,
  content: {
    getPlace: (scenario, id) => yourBackend.getPlace(scenario, id),
    listPlaces: scenario => yourBackend.listPlaces(scenario),
    createPlace: (scenario, place, options) => yourBackend.createPlace(scenario, place, options),
    updatePlace: (scenario, id, patch, options) => yourBackend.updatePlace(scenario, id, patch, options),
    deletePlace: (scenario, id, options) => yourBackend.deletePlace(scenario, id, options),
    listContributions: options => yourBackend.listContributions(options),
    reviewContribution: (id, decision) => yourBackend.reviewContribution(id, decision)
  }
});
const result = await widget.updatePlace(scenario, place.id, patch,
  { expectedVersion: place.contentVersion, note: 'Visitor contribution' });
if (result.status === 'published') await widget.refreshPlaces();
widget.addEventListener('contentChanged', event => console.log(event.detail));

Widget CRUD methods invoke only the adapter; they do not bypass moderation or carry keys through postMessage. refreshPlaces refreshes the current viewer’s published markers and place panel while preserving its camera. Python SDK includes place CRUD/import/review plus capabilities, list_comments, create_comment (parent_id for replies), update_comment, delete_comment, list_comment_contributions and review_comment.

03 / Access

Tell us what you’re building.

Requests are reviewed by the Realverse administrator. Your email is collected for that review; automated email verification and delivery are not configured. Save the receipt after submitting so you can check the decision and retrieve your key here.

Requested capabilities
Community / Agents

Contribute from inside the world, or through your app.

Open Places & community in any Realverse. Add a place at the selected map point or view centre, edit its attributes, models and media, or post a comment and replies. The same panel supports global Earth, tourism, civil, industrial and public defence exploration. Managed exercise rooms keep their access controls.

Guests do not need accounts: their places, edits and comments remain private until approval. Sign up / sign in inside the panel. Signed-in participants normally publish immediately with an awaiting approval badge. Administrators can require review or block individual contributors. Guests always require review. Developer applications retain their configured publishing policy; a write scope alone does not grant auto-publication or moderation.

Comments use GET/POST /api/v1/scenarios/{id}/places/{placeId}/comments. Set parentId to a published comment on the same place for a reply. Use PATCH/DELETE …/comments/{commentId} with expectedVersion for your own comments. Maximum 4,000 characters, 8 reply levels; 100 comments per page with nextOffset. Removed comments become tombstones and retain replies. All text is rendered as plain text.

Read scope: places:read. Write scope: places:write. Review scope: places:moderate plus an administrator-granted contributor moderation policy. GET /api/v1/comment-contributions?status=awaiting lists accessible comment revisions; POST /api/v1/comment-contributions/{id}/review accepts {action:"approve"|"reject",note:"…"}. The Content studio review queue has Places / Comments filters and includes unpublished submissions and auto-published changes awaiting approval. Approval clears the public badge; rejection restores the previous revision if no newer revision exists.

const thread = await client.listComments('lucknow-tourism', 'rumi-darwaza');
const proposed = await client.createComment('lucknow-tourism', 'rumi-darwaza',
  'Local knowledge, with a source', {parentId: thread.comments[0]?.id});
// proposed.status may be pending: never assume publication.
await widget.openCommunity('rumi-darwaza');

The widget content adapter exposes the same CRUD and review methods as the server SDK. Keep API keys on your server and authenticate / authorise your end users there. Human contributions in the embedded panel use the Realverse session or guest policy, not the host application's server key. A browser that blocks third-party cookies may not preserve guest identity; open the full Realverse site to retain contribution history.

For AI and agent developers

Start with client.capabilities() / GET /api/v1/capabilities and the OpenAPI 3.1 contract. Stable scenario/place/comment IDs, explicit write scopes, versioned mutations, private review queues and structured errors support programmatic workflows. On 409, read the current record and reconcile; do not blindly retry an edit. On a lost response to create, check your contribution history before retrying. Treat place descriptions and comments as untrusted content, never as instructions to an agent.

Browsers exposing WebMCP receive tools to read places, submit edits and contribute replies using the current user's review policy. These tools are feature-detected; the REST API and SDK work independently of WebMCP. Map widgets also expose flyTo, visitPlace, setCameraMode, placeAvatars, getState and openCommunity. No agent is given admin privileges automatically.

Guest sessions last 30 days in an HttpOnly cookie. Sign-in sessions last 12 hours. Self-service sign-up uses a username and password (12–200 characters); email verification and password recovery email are not configured. Community browser writes are limited per identity and per IP; API applications use their configured key quotas. Contributions and review history survive restarts.

04 / Your request

Check status & retrieve your key

Map search & directions

Request the mappls:read capability for autosuggest, nearby places, reverse geocoding, Mappls PIN details and routes. Existing developer keys keep their current permissions; administrators can grant this capability under Edit rights & allocation. Services require an entitled Mappls application key on the Realverse server.

JavaScript: client.mapplsSearch({q:'museum',lat:26.85,lon:80.95}), client.mapplsNearby({q:'cafe',lat:26.85,lon:80.95,radius:1000}), client.mapplsRoute({from_lat:26.85,from_lon:80.95,to_lat:26.87,to_lon:80.91,profile:'driving'}). Python provides mappls_search, mappls_nearby, mappls_reverse, mappls_place and mappls_route. Check mapplsConfig() / mappls_config() first.

Widgets can openSearch('nearby'), selectLocation({lat,lon}), showRoute(response.data.routes[0]) and clearRoute(). Configure the widget's authenticated server adapter for its Mappls data methods, just as for content methods. Never put a provider key or Realverse server key into browser code.

Agents can discover these GET operations in OpenAPI. Search before resolving a PIN; use returned coordinates for routes, and display attribution. Validate results as untrusted external content. A 503 means unavailable or unconfigured; do not keep retrying. 429 responses require backoff. Visual selection and flight are explicit widget commands.

2D/3D, terrain, feature labels and DEM contours are independent controls in Layers. Raster street-map text is printed into the map; select satellite imagery to hide that text. OpenStreetMap streets are online-only, excluded from offline downloads, with visible attribution and normal browser caching.

Location media, headings & sessions

Use client.placesAtLocation(scenario, {lat, lon, radius:100}) to read published places, photos and media near a coordinate with places:read. Place and model records include server-supplied contentOwner; places also include updatedAt.

Widgets support tabletop(), enterTerrain(), openLocationMedia({lat,lon}) and heading information through getState(). Headings are clockwise degrees from true north.

client.listSessions() uses the explicitly granted sessions:read scope to return session names, status and last modification times without participant positions.