flexops 1.0.2 → 1.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.
- checksums.yaml +4 -4
- data/README.md +48 -18
- data/lib/flexops/http.rb +5 -3
- data/lib/flexops/resources/shipping.rb +5 -2
- data/lib/flexops/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ae38cf941276d4053203fda4a44fb9ab1adb873d24bba9ec1de7fc634be3e7e2
|
|
4
|
+
data.tar.gz: 43b602d72cbac545bff0391aa2dee8ea28f73bd7807a6042ec17731fe7943881
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0959231eed12a9abd27bc7d370ab9576e32393a131248e231f2d7bebb622c74c29c21596f55036c1af8df73a277a3cbb8ee282c516aca90fc787839c76f102dc'
|
|
7
|
+
data.tar.gz: 42fa01ac062f0f54ed7632e403a0d3a5ed37e3e942e6f11a45797b047f7f343c3b0419d354e83af9be217d58d1877a322ee7fee7fa6c79e9749e069cfca0f7cf
|
data/README.md
CHANGED
|
@@ -40,23 +40,49 @@ rates = client.shipping.get_rates(
|
|
|
40
40
|
package: {weight: 16, weightUnit: "oz"}
|
|
41
41
|
)
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
request = {
|
|
44
|
+
carrierCode: "USPS", serviceCode: "GROUND_ADVANTAGE",
|
|
45
|
+
origin: {name: "Warehouse", addressLine1: "123 Main St", city: "New York", stateProvince: "NY", postalCode: "10001", countryCode: "US"},
|
|
46
|
+
destination: {name: "Customer", addressLine1: "456 Oak Ave", city: "Los Angeles", stateProvince: "CA", postalCode: "90210", countryCode: "US"},
|
|
47
|
+
package: {weight: 16, weightUnit: "oz"},
|
|
48
|
+
maximumPostageAmount: 10.25 # Caller-approved ceiling in USD.
|
|
49
|
+
}
|
|
50
|
+
preview = client.shipping.create_label(request)
|
|
51
|
+
puts preview["quotedPostageAmount"]
|
|
52
|
+
|
|
53
|
+
# Call only after explicit caller approval, within five minutes.
|
|
54
|
+
purchase_approved_label = lambda do |purchase_key|
|
|
55
|
+
client.shipping.create_label(
|
|
56
|
+
request.merge(confirmationToken: preview["confirmationToken"]),
|
|
57
|
+
idempotency_key: purchase_key # Persist per purchase; reuse on retries.
|
|
58
|
+
)
|
|
59
|
+
end
|
|
55
60
|
|
|
56
61
|
# Track a shipment
|
|
57
62
|
info = client.shipping.track("9400111899223456789012")
|
|
58
63
|
```
|
|
59
64
|
|
|
65
|
+
### Live label approval (1.1.0+)
|
|
66
|
+
|
|
67
|
+
The example below requires SDK 1.1.0 or later. Version 1.0.2 does not
|
|
68
|
+
include the per-call idempotency argument.
|
|
69
|
+
|
|
70
|
+
For live domestic single-label requests, `maximumPostageAmount` is required: positive
|
|
71
|
+
USD, at most two decimal places, up to 1,000,000. Missing or invalid values return
|
|
72
|
+
400 `ApprovalRequired`. Omitting `confirmationToken` returns a raw 200 preview
|
|
73
|
+
(`status`, `quotedPostageAmount`, `maximumPostageAmount`, `currency`, `expiresAt`,
|
|
74
|
+
`confirmationToken`). After explicit approval, resubmit the same shipment and ceiling
|
|
75
|
+
with the token and a unique per-purchase `Idempotency-Key` header. The token expires
|
|
76
|
+
after five minutes. A successful purchase returns the raw 201 label, including
|
|
77
|
+
`labelId`, `trackingNumber`, `carrierCode`, and `labelData`, without a `data` wrapper.
|
|
78
|
+
|
|
79
|
+
Keep the same key and request across retries. An uncertain outcome needs reconciliation;
|
|
80
|
+
do not start another purchase with a new key. An expired approval returns 409
|
|
81
|
+
`ApprovalExpired`; obtain and explicitly approve a fresh preview when no purchase is
|
|
82
|
+
unresolved. The ceiling bounds postage authorization, not later adjustments or separate
|
|
83
|
+
fees. Sandbox execution bypasses approval; batch, return, and raw carrier routes have
|
|
84
|
+
separate contracts. The SDK never automatically confirms a preview.
|
|
85
|
+
|
|
60
86
|
## Authentication
|
|
61
87
|
|
|
62
88
|
### API key (recommended)
|
|
@@ -128,18 +154,22 @@ curl -X POST https://gateway.flexops.io/api/shipping/rates \
|
|
|
128
154
|
"package": {"weight": 16, "weightUnit": "oz"}
|
|
129
155
|
}'
|
|
130
156
|
|
|
131
|
-
#
|
|
157
|
+
# Preview a live label; this does not purchase it.
|
|
132
158
|
curl -X POST https://gateway.flexops.io/api/workspaces/ws_abc123/shipping/labels \
|
|
133
159
|
-H "X-API-Key: fxk_live_..." \
|
|
134
160
|
-H "Content-Type: application/json" \
|
|
135
161
|
-d '{
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
"
|
|
162
|
+
"carrierCode": "USPS", "serviceCode": "GROUND_ADVANTAGE",
|
|
163
|
+
"origin": {"name": "Warehouse", "addressLine1": "123 Main St", "city": "New York", "stateProvince": "NY", "postalCode": "10001", "countryCode": "US"},
|
|
164
|
+
"destination": {"name": "Customer", "addressLine1": "456 Oak Ave", "city": "Los Angeles", "stateProvince": "CA", "postalCode": "90210", "countryCode": "US"},
|
|
165
|
+
"package": {"weight": 16, "weightUnit": "oz"},
|
|
166
|
+
"maximumPostageAmount": 10.25
|
|
141
167
|
}'
|
|
142
168
|
|
|
169
|
+
# After explicit approval, resend the same body with confirmationToken from
|
|
170
|
+
# the preview and an Idempotency-Key header unique to this purchase.
|
|
171
|
+
# See the SDK example above; retain that key for retries.
|
|
172
|
+
|
|
143
173
|
# Track a shipment
|
|
144
174
|
curl https://gateway.flexops.io/api/workspaces/ws_abc123/shipping/track/9400111899223456789012 \
|
|
145
175
|
-H "X-API-Key: fxk_live_..."
|
data/lib/flexops/http.rb
CHANGED
|
@@ -38,8 +38,8 @@ module FlexOps
|
|
|
38
38
|
request(:get, path, query: query)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
def post(path, body: nil, query: nil)
|
|
42
|
-
request(:post, path, body: body, query: query)
|
|
41
|
+
def post(path, body: nil, query: nil, headers: {})
|
|
42
|
+
request(:post, path, body: body, query: query, headers: headers)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def put(path, body: nil)
|
|
@@ -56,7 +56,7 @@ module FlexOps
|
|
|
56
56
|
|
|
57
57
|
private
|
|
58
58
|
|
|
59
|
-
def request(method, path, body: nil, query: nil)
|
|
59
|
+
def request(method, path, body: nil, query: nil, headers: {})
|
|
60
60
|
uri = build_uri(path, query)
|
|
61
61
|
last_error = nil
|
|
62
62
|
|
|
@@ -66,6 +66,7 @@ module FlexOps
|
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
req = build_request(method, uri, body)
|
|
69
|
+
headers.each { |name, value| req[name] = value }
|
|
69
70
|
begin
|
|
70
71
|
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https",
|
|
71
72
|
open_timeout: @timeout, read_timeout: @timeout) do |http|
|
|
@@ -97,6 +98,7 @@ module FlexOps
|
|
|
97
98
|
error = Error.new(
|
|
98
99
|
error_body["message"] || "HTTP #{status}: #{response.message}",
|
|
99
100
|
status: status,
|
|
101
|
+
code: error_body["errorCode"] || error_body["code"],
|
|
100
102
|
errors: error_body["errors"]
|
|
101
103
|
)
|
|
102
104
|
|
|
@@ -26,8 +26,11 @@ module FlexOps
|
|
|
26
26
|
@http.post("/api/shipping/rates/fastest", body: request)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
# Returns a raw preview or label; confirmation always belongs to the caller.
|
|
30
|
+
def create_label(request = {}, idempotency_key: nil, **fields)
|
|
31
|
+
request = request.merge(fields)
|
|
32
|
+
@http.post("#{ws_path}/shipping/labels", body: request,
|
|
33
|
+
headers: idempotency_key.nil? ? {} : { "Idempotency-Key" => idempotency_key })
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
def cancel_label(label_id)
|
data/lib/flexops/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: flexops
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- FlexOps, LLC
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: json
|