HTTP API

XPARO has three HTTP interfaces. Everything on this page was run against an XPARO server; the responses shown are real.

Address

Signs in with

For

/chatbot_api/<key>/<project-id>/

the secret key or the robot’s credential, in the address

Robots: get the project sync, send any robot message.

/api/upload_rosbag/

Authorization: Token <REST_API_TOKEN>

Robots: upload recordings.

/get_project_data/-/<project-id>/

your XPARO username and password

Your own scripts: read project data.

All addresses start with https://xparo.in.

Robot API

GET returns the same project sync a robot receives when its WebSocket connects:

curl https://xparo.in/chatbot_api/<secret-key>/<project-id>/
{"title": "Hospital Delivery Bot", "status": true, "aiml": "...", "custom_aiml": {...},
 "maps": "...", "custom_maps": {...}, "Sets": "...", "custom_Sets": {...}, "properties": "...",
 "custom_tasks": {...}, "custom_node_files": {...}, "System": ""}

POST takes one JSON message, exactly as it would be sent over the WebSocket (see Message catalogue), and returns the server’s reply, {} when there is none. This is how xparo_ros sends its heartbeat:

curl -X POST -H "Content-Type: application/json" \
  -d '{"ROBOT_HEARTBEAT": {"device_id": "my-robot-0001"}}' \
  https://xparo.in/chatbot_api/<key>/<project-id>/
{}

Things to know:

  • Every response has status 201, including errors. A wrong key returns {"error": "user not exists go to ... and check"}, so check the body, not only the status.

  • HTTP is one way: the robot asks, the server answers. Dashboard commands (Run now, terminal, teleop, files…) cannot reach a robot this way; they need the WebSocket (Connection protocol).

Uploading recordings

xparo_ros uploads ROS bag files here (see ROS bag recording). The token is the REST_API_TOKEN the server sends in reply to ADD_robots_info.

curl -H "Authorization: Token <REST_API_TOKEN>" \
  -F "bag_file=@rosbag2_2026_10_06-08_30_00_0.mcap.zstd" \
  -F "robot_id=my-robot-0001" \
  -F 'data={"note": "test"}' \
  https://xparo.in/api/upload_rosbag/
{"status":"success","message":"File rosbag2_2026_10_06-08_30_00_0.mcap.zstd saved to Azure","db_id":"9d022794-bec6-48e1-8adf-ef0d0f78a2ff"}

robot_id is the robot’s device_id; data is optional JSON stored with the file. The file appears in Database → Sensors.

Status

Meaning

201

Stored.

400

No bag_file in the request.

401

No token: {"detail":"Authentication credentials were not provided."}

402

The project is out of storage credits. Uploads pause until you top up; existing data is kept.

403

The token’s account is not a member of the robot’s project, or is a Viewer.

404

No robot with that robot_id.

Reading project data from a script

/get_project_data/-/<project-id>/ lets a script read what the dashboard shows, signing in with your XPARO username and password (HTTP Basic). It takes a form field data holding the same JSON the dashboard sends; the answer is under u → project ID.

import json
import requests

SERVER = "https://xparo.in"
PROJECT_ID = "<your-project-id>"
AUTH = ("<your-username>", "<your-password>")


def ask(key, payload):
    data = json.dumps({"p": {PROJECT_ID: {key: payload}}})
    reply = requests.post(f"{SERVER}/get_project_data/-/{PROJECT_ID}/",
                          data={"data": data}, auth=AUTH, timeout=30)
    reply.raise_for_status()
    return reply.json()["u"][PROJECT_ID]


for task in ask("GET_services", {})["services"]:
    print(task["id"], task["title"], task["status"])

history = ask("GET_Task_history_database", {"current_page": 1})["task_history"]
print(history["totalRecords"], "runs saved")
for run in history["records"]:
    out = run["fields"]["output_data"]
    print(run["fields"]["created_at"], out.get("outcome"), f"{out.get('duration_s', 0):.1f}s")

Output:

3dffb995-298e-4335-a0a9-b38aecc396fa Deliver medicine development
2 runs saved
2026-10-06T02:30:03.340Z failed 0.3s
2026-10-06T02:29:47.379Z success 11.9s
curl -u '<your-username>:<your-password>' \
  --data-urlencode 'data={"p": {"<project-id>": {"GET_Task_history_database": {"current_page": 1}}}}' \
  https://xparo.in/get_project_data/-/<project-id>/
{"u": {"<project-id>": {"task_history": {"records": [...], "totalRecords": 2,
 "currentPage": 1, "pageSize": 10, "columns": ["id", "type", "created_at"]}}}}

GET_services lists the project’s tasks; GET_Task_history_database returns saved task runs, 10 per page. Without a username and password, or with a wrong one, the answer is 403.

You can read data this way, but you cannot run or cancel tasks: RUN_TASK answers

{"error": "RUN_TASK cannot be dispatched over the REST endpoint -- it requires a live robot connection to relay to. Use the dashboard's live session instead."}

To start a task from outside the dashboard, publish on the robot’s /xparo/run_task topic instead.

Reports

The PDF report and Excel buttons on the project’s Dashboard page (/api/download-report/pdf/<project-slug>/ and .../excel/...) need a signed-in browser session. They are not available to scripts.