robomart 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- robomart-0.1.0/PKG-INFO +41 -0
- robomart-0.1.0/README.md +24 -0
- robomart-0.1.0/pyproject.toml +27 -0
- robomart-0.1.0/robomart/__init__.py +149 -0
- robomart-0.1.0/robomart.egg-info/PKG-INFO +41 -0
- robomart-0.1.0/robomart.egg-info/SOURCES.txt +7 -0
- robomart-0.1.0/robomart.egg-info/dependency_links.txt +1 -0
- robomart-0.1.0/robomart.egg-info/top_level.txt +1 -0
- robomart-0.1.0/setup.cfg +4 -0
robomart-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: robomart
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client for the Robomart Network Delivery API
|
|
5
|
+
Author-email: Robomart <ali@robomart.ai>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://robomart.ai
|
|
8
|
+
Project-URL: Documentation, https://api.robomart.ai
|
|
9
|
+
Project-URL: Repository, https://github.com/robomart-ai/api
|
|
10
|
+
Keywords: robomart,delivery,robocourier,robot,api,sdk
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# robomart
|
|
19
|
+
|
|
20
|
+
Python client for the Robomart Network Delivery API — coverage preview, one-step booking at posted flat rates, tracking, proof of delivery, and wallet reads. Mirrors the [TypeScript SDK](https://www.npmjs.com/package/robomart).
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from robomart import Robomart
|
|
24
|
+
|
|
25
|
+
rm = Robomart("rm_sk_test_...")
|
|
26
|
+
|
|
27
|
+
route = rm.delivery.coverage({
|
|
28
|
+
"pickup": {"address": "8080 Park Ln, Dallas, TX"},
|
|
29
|
+
"dropoff": {"address": "2323 N Field St, Dallas, TX"},
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
order = rm.delivery.book({
|
|
33
|
+
"pickup": {"address": "...", "contact": {"name": "...", "phone": "..."}},
|
|
34
|
+
"dropoff": {"address": "...", "contact": {"name": "...", "phone": "..."}},
|
|
35
|
+
"parcel": {"length_in": 12, "width_in": 10, "height_in": 8, "weight_lb": 5},
|
|
36
|
+
}, idempotency_key="order-1")
|
|
37
|
+
|
|
38
|
+
status = rm.delivery.get(order["id"])
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Get a key at [console.robomart.ai](https://console.robomart.ai). AI agents can book directly through the Delivery MCP at `mcp.robomart.ai` with the same key.
|
robomart-0.1.0/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# robomart
|
|
2
|
+
|
|
3
|
+
Python client for the Robomart Network Delivery API — coverage preview, one-step booking at posted flat rates, tracking, proof of delivery, and wallet reads. Mirrors the [TypeScript SDK](https://www.npmjs.com/package/robomart).
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from robomart import Robomart
|
|
7
|
+
|
|
8
|
+
rm = Robomart("rm_sk_test_...")
|
|
9
|
+
|
|
10
|
+
route = rm.delivery.coverage({
|
|
11
|
+
"pickup": {"address": "8080 Park Ln, Dallas, TX"},
|
|
12
|
+
"dropoff": {"address": "2323 N Field St, Dallas, TX"},
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
order = rm.delivery.book({
|
|
16
|
+
"pickup": {"address": "...", "contact": {"name": "...", "phone": "..."}},
|
|
17
|
+
"dropoff": {"address": "...", "contact": {"name": "...", "phone": "..."}},
|
|
18
|
+
"parcel": {"length_in": 12, "width_in": 10, "height_in": 8, "weight_lb": 5},
|
|
19
|
+
}, idempotency_key="order-1")
|
|
20
|
+
|
|
21
|
+
status = rm.delivery.get(order["id"])
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Get a key at [console.robomart.ai](https://console.robomart.ai). AI agents can book directly through the Delivery MCP at `mcp.robomart.ai` with the same key.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "robomart"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python client for the Robomart Network Delivery API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Robomart", email = "ali@robomart.ai" }]
|
|
13
|
+
keywords = ["robomart", "delivery", "robocourier", "robot", "api", "sdk"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://robomart.ai"
|
|
23
|
+
Documentation = "https://api.robomart.ai"
|
|
24
|
+
Repository = "https://github.com/robomart-ai/api"
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.packages.find]
|
|
27
|
+
include = ["robomart*"]
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""Python client for the Robomart Network Delivery API.
|
|
2
|
+
|
|
3
|
+
Prices are posted flat rates, so there is no quote step: preview a route
|
|
4
|
+
with coverage() and book in one call with book().
|
|
5
|
+
|
|
6
|
+
from robomart import Robomart
|
|
7
|
+
|
|
8
|
+
rm = Robomart("rm_sk_test_...")
|
|
9
|
+
route = rm.delivery.coverage({
|
|
10
|
+
"pickup": {"address": "..."},
|
|
11
|
+
"dropoff": {"address": "..."},
|
|
12
|
+
})
|
|
13
|
+
order = rm.delivery.book({...}, idempotency_key="order-1")
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
import urllib.error
|
|
20
|
+
import urllib.request
|
|
21
|
+
|
|
22
|
+
__all__ = ["Robomart", "RobomartError"]
|
|
23
|
+
__version__ = "0.1.0"
|
|
24
|
+
|
|
25
|
+
DEFAULT_BASE_URL = "https://api.robomart.ai"
|
|
26
|
+
DEFAULT_API_VERSION = "2026-08-27"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class RobomartError(Exception):
|
|
30
|
+
"""API error carrying the HTTP status and the error envelope."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, message, status=None, type=None, code=None):
|
|
33
|
+
super().__init__(message)
|
|
34
|
+
self.status = status
|
|
35
|
+
self.type = type
|
|
36
|
+
self.code = code
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class _Http:
|
|
40
|
+
def __init__(self, api_key, base_url, api_version):
|
|
41
|
+
self.api_key = api_key
|
|
42
|
+
self.base_url = base_url.rstrip("/")
|
|
43
|
+
self.api_version = api_version
|
|
44
|
+
|
|
45
|
+
def request(self, method, path, body=None, extra_headers=None):
|
|
46
|
+
headers = {
|
|
47
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
48
|
+
"Content-Type": "application/json",
|
|
49
|
+
"Robomart-Version": self.api_version,
|
|
50
|
+
"User-Agent": f"robomart-python/{__version__}",
|
|
51
|
+
}
|
|
52
|
+
if extra_headers:
|
|
53
|
+
headers.update(extra_headers)
|
|
54
|
+
data = json.dumps(body).encode() if body is not None else None
|
|
55
|
+
req = urllib.request.Request(
|
|
56
|
+
self.base_url + path, data=data, headers=headers, method=method
|
|
57
|
+
)
|
|
58
|
+
try:
|
|
59
|
+
with urllib.request.urlopen(req) as resp:
|
|
60
|
+
return json.loads(resp.read() or b"{}")
|
|
61
|
+
except urllib.error.HTTPError as err:
|
|
62
|
+
try:
|
|
63
|
+
payload = json.loads(err.read() or b"{}")
|
|
64
|
+
except ValueError:
|
|
65
|
+
payload = {}
|
|
66
|
+
detail = payload.get("error")
|
|
67
|
+
detail = detail if isinstance(detail, dict) else {}
|
|
68
|
+
message = (
|
|
69
|
+
detail.get("message")
|
|
70
|
+
or payload.get("error")
|
|
71
|
+
or payload.get("message")
|
|
72
|
+
or f"Request failed with status {err.code}"
|
|
73
|
+
)
|
|
74
|
+
raise RobomartError(
|
|
75
|
+
message, status=err.code,
|
|
76
|
+
type=detail.get("type"), code=detail.get("code"),
|
|
77
|
+
) from None
|
|
78
|
+
|
|
79
|
+
def get(self, path):
|
|
80
|
+
return self.request("GET", path)
|
|
81
|
+
|
|
82
|
+
def post(self, path, body=None, extra_headers=None):
|
|
83
|
+
return self.request("POST", path, body, extra_headers)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Delivery:
|
|
87
|
+
"""Coverage preview, one-step booking, tracking, cancellation, proof."""
|
|
88
|
+
|
|
89
|
+
def __init__(self, http):
|
|
90
|
+
self._http = http
|
|
91
|
+
|
|
92
|
+
def coverage(self, input):
|
|
93
|
+
"""Read-only route preview: eligibility, mode, and the posted fee."""
|
|
94
|
+
return self._http.post("/v1/coverage", input)
|
|
95
|
+
|
|
96
|
+
def book(self, input, idempotency_key):
|
|
97
|
+
"""One-step booking at the posted price. The idempotency key makes
|
|
98
|
+
a retried call replay the original booking instead of double booking."""
|
|
99
|
+
result = self._http.post(
|
|
100
|
+
"/v1/deliveries", input, {"Idempotency-Key": idempotency_key}
|
|
101
|
+
)
|
|
102
|
+
return result["data"]
|
|
103
|
+
|
|
104
|
+
def get(self, id):
|
|
105
|
+
return self._http.get(f"/v1/deliveries/{id}")["data"]
|
|
106
|
+
|
|
107
|
+
def list(self, limit=None):
|
|
108
|
+
qs = f"?limit={limit}" if limit else ""
|
|
109
|
+
return self._http.get(f"/v1/deliveries{qs}")["data"]
|
|
110
|
+
|
|
111
|
+
def cancel(self, id):
|
|
112
|
+
"""Cancel before pickup releases the full posted price. After pickup
|
|
113
|
+
the trip stays charged and the call is refused."""
|
|
114
|
+
return self._http.post(f"/v1/deliveries/{id}/cancel")["data"]
|
|
115
|
+
|
|
116
|
+
def proof(self, id):
|
|
117
|
+
"""Proof of delivery, available once the delivery is delivered."""
|
|
118
|
+
return self._http.get(f"/v1/deliveries/{id}/proof")["data"]
|
|
119
|
+
|
|
120
|
+
def simulate(self, id, action):
|
|
121
|
+
"""Sandbox lifecycle driver. Test keys only."""
|
|
122
|
+
return self._http.post(f"/v1/deliveries/{id}/simulate", {"action": action})["data"]
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class Wallet:
|
|
126
|
+
"""Balances, the ledger, and funding previews. Cents throughout."""
|
|
127
|
+
|
|
128
|
+
def __init__(self, http):
|
|
129
|
+
self._http = http
|
|
130
|
+
|
|
131
|
+
def balance(self):
|
|
132
|
+
return self._http.get("/v1/balance")
|
|
133
|
+
|
|
134
|
+
def ledger(self, limit=None):
|
|
135
|
+
qs = f"?limit={limit}" if limit else ""
|
|
136
|
+
return self._http.get(f"/v1/ledger{qs}")["data"]
|
|
137
|
+
|
|
138
|
+
def topup_preview(self, amount_credited_cents):
|
|
139
|
+
return self._http.get(f"/v1/topups/preview?amount_credited={amount_credited_cents}")
|
|
140
|
+
|
|
141
|
+
def topup_link(self):
|
|
142
|
+
return self._http.post("/v1/topups/link")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class Robomart:
|
|
146
|
+
def __init__(self, api_key, base_url=DEFAULT_BASE_URL, api_version=DEFAULT_API_VERSION):
|
|
147
|
+
http = _Http(api_key, base_url, api_version)
|
|
148
|
+
self.delivery = Delivery(http)
|
|
149
|
+
self.wallet = Wallet(http)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: robomart
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client for the Robomart Network Delivery API
|
|
5
|
+
Author-email: Robomart <ali@robomart.ai>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://robomart.ai
|
|
8
|
+
Project-URL: Documentation, https://api.robomart.ai
|
|
9
|
+
Project-URL: Repository, https://github.com/robomart-ai/api
|
|
10
|
+
Keywords: robomart,delivery,robocourier,robot,api,sdk
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# robomart
|
|
19
|
+
|
|
20
|
+
Python client for the Robomart Network Delivery API — coverage preview, one-step booking at posted flat rates, tracking, proof of delivery, and wallet reads. Mirrors the [TypeScript SDK](https://www.npmjs.com/package/robomart).
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from robomart import Robomart
|
|
24
|
+
|
|
25
|
+
rm = Robomart("rm_sk_test_...")
|
|
26
|
+
|
|
27
|
+
route = rm.delivery.coverage({
|
|
28
|
+
"pickup": {"address": "8080 Park Ln, Dallas, TX"},
|
|
29
|
+
"dropoff": {"address": "2323 N Field St, Dallas, TX"},
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
order = rm.delivery.book({
|
|
33
|
+
"pickup": {"address": "...", "contact": {"name": "...", "phone": "..."}},
|
|
34
|
+
"dropoff": {"address": "...", "contact": {"name": "...", "phone": "..."}},
|
|
35
|
+
"parcel": {"length_in": 12, "width_in": 10, "height_in": 8, "weight_lb": 5},
|
|
36
|
+
}, idempotency_key="order-1")
|
|
37
|
+
|
|
38
|
+
status = rm.delivery.get(order["id"])
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Get a key at [console.robomart.ai](https://console.robomart.ai). AI agents can book directly through the Delivery MCP at `mcp.robomart.ai` with the same key.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
robomart
|
robomart-0.1.0/setup.cfg
ADDED