robomart 0.1.0

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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +22 -0
  3. data/lib/robomart.rb +128 -0
  4. metadata +48 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cd2a2725dee3756af4ced35a76ca4da675eb960ac6bbeb2f7298cdf14102582a
4
+ data.tar.gz: ccb62fe68e1e5cd4f2813d90e0e8e03e8c926fbe3961f52cb3b3f300cfa9fe5c
5
+ SHA512:
6
+ metadata.gz: 5841e066dc5d22e359ccea303eeb84863c090b923b0ae88e5d36dd81a2d0250ccd661140f08e3c9b134a3a233258e2c2df1e224e6bb9903fc612311518c850c7
7
+ data.tar.gz: ff161671c8a842d34d04e104923b8a226eecb50fd69673a6f50daf4eece56147ba37290608a7b3ea6f3e727a29c6bc72f3f079b0e4a196d367fa5db21bc12b29
data/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # robomart
2
+
3
+ Ruby client for the Robomart Network Delivery API — coverage preview, one-step booking at posted flat rates, tracking, proof of delivery, and wallet reads.
4
+
5
+ ```ruby
6
+ require "robomart"
7
+
8
+ rm = Robomart::Client.new("rm_sk_test_...")
9
+
10
+ route = rm.coverage(
11
+ pickup: { address: "8080 Park Ln, Dallas, TX" },
12
+ dropoff: { address: "2323 N Field St, Dallas, TX" }
13
+ )
14
+
15
+ order = rm.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
+
22
+ 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.
data/lib/robomart.rb ADDED
@@ -0,0 +1,128 @@
1
+ # Ruby 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.
5
+ #
6
+ # rm = Robomart::Client.new("rm_sk_test_...")
7
+ # route = rm.coverage(pickup: { address: "..." }, dropoff: { address: "..." })
8
+ # order = rm.book({ ... }, idempotency_key: "order-1")
9
+
10
+ require "json"
11
+ require "net/http"
12
+ require "uri"
13
+
14
+ module Robomart
15
+ VERSION = "0.1.0"
16
+ DEFAULT_BASE_URL = "https://api.robomart.ai"
17
+ DEFAULT_API_VERSION = "2026-08-27"
18
+
19
+ # API error carrying the HTTP status and the error envelope.
20
+ class Error < StandardError
21
+ attr_reader :status, :type, :code
22
+
23
+ def initialize(message, status: nil, type: nil, code: nil)
24
+ super(message)
25
+ @status = status
26
+ @type = type
27
+ @code = code
28
+ end
29
+ end
30
+
31
+ class Client
32
+ def initialize(api_key, base_url: DEFAULT_BASE_URL, api_version: DEFAULT_API_VERSION)
33
+ @api_key = api_key
34
+ @base_url = base_url.sub(%r{/\z}, "")
35
+ @api_version = api_version
36
+ end
37
+
38
+ # Read-only route preview: eligibility, mode, and the posted fee.
39
+ def coverage(input)
40
+ post("/v1/coverage", input)
41
+ end
42
+
43
+ # One-step booking at the posted price. The idempotency key makes a
44
+ # retried call replay the original booking instead of double booking.
45
+ def book(input, idempotency_key:)
46
+ post("/v1/deliveries", input, { "Idempotency-Key" => idempotency_key }).fetch("data")
47
+ end
48
+
49
+ def delivery(id)
50
+ get("/v1/deliveries/#{id}").fetch("data")
51
+ end
52
+
53
+ def deliveries(limit: nil)
54
+ qs = limit ? "?limit=#{limit}" : ""
55
+ get("/v1/deliveries#{qs}").fetch("data")
56
+ end
57
+
58
+ # Cancel before pickup releases the full posted price. After pickup the
59
+ # trip stays charged and the call is refused.
60
+ def cancel(id)
61
+ post("/v1/deliveries/#{id}/cancel").fetch("data")
62
+ end
63
+
64
+ # Proof of delivery, available once the delivery is delivered.
65
+ def proof(id)
66
+ get("/v1/deliveries/#{id}/proof").fetch("data")
67
+ end
68
+
69
+ # Sandbox lifecycle driver. Test keys only.
70
+ def simulate(id, action)
71
+ post("/v1/deliveries/#{id}/simulate", { action: action }).fetch("data")
72
+ end
73
+
74
+ # Wallet reads. Cents throughout.
75
+ def balance
76
+ get("/v1/balance")
77
+ end
78
+
79
+ def ledger(limit: nil)
80
+ qs = limit ? "?limit=#{limit}" : ""
81
+ get("/v1/ledger#{qs}").fetch("data")
82
+ end
83
+
84
+ def topup_preview(amount_credited_cents)
85
+ get("/v1/topups/preview?amount_credited=#{amount_credited_cents}")
86
+ end
87
+
88
+ def topup_link
89
+ post("/v1/topups/link")
90
+ end
91
+
92
+ private
93
+
94
+ def get(path)
95
+ request(Net::HTTP::Get, path)
96
+ end
97
+
98
+ def post(path, body = nil, extra_headers = {})
99
+ request(Net::HTTP::Post, path, body, extra_headers)
100
+ end
101
+
102
+ def request(verb, path, body = nil, extra_headers = {})
103
+ uri = URI.parse(@base_url + path)
104
+ req = verb.new(uri)
105
+ req["Authorization"] = "Bearer #{@api_key}"
106
+ req["Content-Type"] = "application/json"
107
+ req["Robomart-Version"] = @api_version
108
+ req["User-Agent"] = "robomart-ruby/#{VERSION}"
109
+ extra_headers.each { |k, v| req[k] = v }
110
+ req.body = JSON.generate(body) if body
111
+
112
+ res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
113
+ http.request(req)
114
+ end
115
+ payload = begin
116
+ JSON.parse(res.body.to_s.empty? ? "{}" : res.body)
117
+ rescue JSON::ParserError
118
+ {}
119
+ end
120
+ return payload if res.is_a?(Net::HTTPSuccess)
121
+
122
+ detail = payload["error"].is_a?(Hash) ? payload["error"] : {}
123
+ message = detail["message"] || payload["error"] || payload["message"] ||
124
+ "Request failed with status #{res.code}"
125
+ raise Error.new(message, status: res.code.to_i, type: detail["type"], code: detail["code"])
126
+ end
127
+ end
128
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: robomart
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Robomart
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-08-30 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Coverage preview, one-step booking at posted flat rates, tracking, proof
14
+ of delivery, and wallet reads for the Robomart Network.
15
+ email:
16
+ - ali@robomart.ai
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - README.md
22
+ - lib/robomart.rb
23
+ homepage: https://robomart.ai
24
+ licenses:
25
+ - MIT
26
+ metadata:
27
+ source_code_uri: https://github.com/robomart-ai/api
28
+ documentation_uri: https://api.robomart.ai
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '2.6'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubygems_version: 3.0.3.1
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Ruby client for the Robomart Network Delivery API
48
+ test_files: []