karrio-cli 2025.5rc3__py3-none-any.whl

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 (68) hide show
  1. karrio_cli/__init__.py +0 -0
  2. karrio_cli/__main__.py +105 -0
  3. karrio_cli/ai/README.md +335 -0
  4. karrio_cli/ai/__init__.py +0 -0
  5. karrio_cli/ai/commands.py +102 -0
  6. karrio_cli/ai/karrio_ai/__init__.py +1 -0
  7. karrio_cli/ai/karrio_ai/agent.py +972 -0
  8. karrio_cli/ai/karrio_ai/architecture/INTEGRATION_AGENT_PROMPT.md +497 -0
  9. karrio_cli/ai/karrio_ai/architecture/MAPPING_AGENT_PROMPT.md +355 -0
  10. karrio_cli/ai/karrio_ai/architecture/REAL_WORLD_TESTING.md +305 -0
  11. karrio_cli/ai/karrio_ai/architecture/SCHEMA_AGENT_PROMPT.md +183 -0
  12. karrio_cli/ai/karrio_ai/architecture/TESTING_AGENT_PROMPT.md +448 -0
  13. karrio_cli/ai/karrio_ai/architecture/TESTING_GUIDE.md +271 -0
  14. karrio_cli/ai/karrio_ai/enhanced_tools.py +943 -0
  15. karrio_cli/ai/karrio_ai/rag_system.py +503 -0
  16. karrio_cli/ai/karrio_ai/tests/test_agent.py +350 -0
  17. karrio_cli/ai/karrio_ai/tests/test_real_integration.py +360 -0
  18. karrio_cli/ai/karrio_ai/tests/test_real_world_scenarios.py +513 -0
  19. karrio_cli/commands/__init__.py +0 -0
  20. karrio_cli/commands/codegen.py +336 -0
  21. karrio_cli/commands/login.py +139 -0
  22. karrio_cli/commands/plugins.py +168 -0
  23. karrio_cli/commands/sdk.py +870 -0
  24. karrio_cli/common/queries.py +101 -0
  25. karrio_cli/common/utils.py +368 -0
  26. karrio_cli/resources/__init__.py +0 -0
  27. karrio_cli/resources/carriers.py +91 -0
  28. karrio_cli/resources/connections.py +207 -0
  29. karrio_cli/resources/events.py +151 -0
  30. karrio_cli/resources/logs.py +151 -0
  31. karrio_cli/resources/orders.py +144 -0
  32. karrio_cli/resources/shipments.py +210 -0
  33. karrio_cli/resources/trackers.py +287 -0
  34. karrio_cli/templates/__init__.py +9 -0
  35. karrio_cli/templates/__pycache__/__init__.cpython-311.pyc +0 -0
  36. karrio_cli/templates/__pycache__/__init__.cpython-312.pyc +0 -0
  37. karrio_cli/templates/__pycache__/address.cpython-311.pyc +0 -0
  38. karrio_cli/templates/__pycache__/address.cpython-312.pyc +0 -0
  39. karrio_cli/templates/__pycache__/docs.cpython-311.pyc +0 -0
  40. karrio_cli/templates/__pycache__/docs.cpython-312.pyc +0 -0
  41. karrio_cli/templates/__pycache__/documents.cpython-311.pyc +0 -0
  42. karrio_cli/templates/__pycache__/documents.cpython-312.pyc +0 -0
  43. karrio_cli/templates/__pycache__/manifest.cpython-311.pyc +0 -0
  44. karrio_cli/templates/__pycache__/manifest.cpython-312.pyc +0 -0
  45. karrio_cli/templates/__pycache__/pickup.cpython-311.pyc +0 -0
  46. karrio_cli/templates/__pycache__/pickup.cpython-312.pyc +0 -0
  47. karrio_cli/templates/__pycache__/rates.cpython-311.pyc +0 -0
  48. karrio_cli/templates/__pycache__/rates.cpython-312.pyc +0 -0
  49. karrio_cli/templates/__pycache__/sdk.cpython-311.pyc +0 -0
  50. karrio_cli/templates/__pycache__/sdk.cpython-312.pyc +0 -0
  51. karrio_cli/templates/__pycache__/shipments.cpython-311.pyc +0 -0
  52. karrio_cli/templates/__pycache__/shipments.cpython-312.pyc +0 -0
  53. karrio_cli/templates/__pycache__/tracking.cpython-311.pyc +0 -0
  54. karrio_cli/templates/__pycache__/tracking.cpython-312.pyc +0 -0
  55. karrio_cli/templates/address.py +308 -0
  56. karrio_cli/templates/docs.py +150 -0
  57. karrio_cli/templates/documents.py +428 -0
  58. karrio_cli/templates/manifest.py +396 -0
  59. karrio_cli/templates/pickup.py +839 -0
  60. karrio_cli/templates/rates.py +638 -0
  61. karrio_cli/templates/sdk.py +947 -0
  62. karrio_cli/templates/shipments.py +892 -0
  63. karrio_cli/templates/tracking.py +437 -0
  64. karrio_cli-2025.5rc3.dist-info/METADATA +165 -0
  65. karrio_cli-2025.5rc3.dist-info/RECORD +68 -0
  66. karrio_cli-2025.5rc3.dist-info/WHEEL +5 -0
  67. karrio_cli-2025.5rc3.dist-info/entry_points.txt +2 -0
  68. karrio_cli-2025.5rc3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,207 @@
1
+ import typer
2
+ import karrio_cli.common.utils as utils
3
+ import typing
4
+
5
+ app = typer.Typer()
6
+
7
+ @app.command("list")
8
+ def list_connections(
9
+ carrier_name: typing.Optional[str] = None,
10
+ system_only: bool = typer.Option(False, "--system-only", help="Filter for system connections only"),
11
+ limit: int = typer.Option(20, help="Number of results to return per page"),
12
+ offset: int = typer.Option(0, help="The initial index from which to return the results"),
13
+ pretty: bool = typer.Option(False, "--pretty", "-p", help="Pretty print the output"),
14
+ line_numbers: bool = typer.Option(False, "--line-numbers", "-n", help="Show line numbers in pretty print"),
15
+ ):
16
+ """
17
+ List all carrier connections with optional filters and pagination.
18
+
19
+ Examples:
20
+ ```terminal
21
+ # Get all connections and display as a table
22
+ kcli connections list | jq -r ".results[] | [.id, .carrier_name, .test_mode] | @tsv" | column -t -s $"\t"
23
+ ```
24
+
25
+ ```terminal
26
+ # Get connections for a specific carrier
27
+ kcli connections list --carrier-name ups | jq ".results[] | {id, carrier_name, test_mode}"
28
+ ```
29
+
30
+ Example Output:
31
+ ```json
32
+ {
33
+ "count": 2,
34
+ "next": null,
35
+ "previous": null,
36
+ "results": [
37
+ {
38
+ "id": "conn_123456789",
39
+ "carrier_name": "ups",
40
+ "test_mode": true,
41
+ "active": true,
42
+ "capabilities": ["rating", "shipping", "tracking"],
43
+ "metadata": {}
44
+ }
45
+ ]
46
+ }
47
+ ```
48
+ """
49
+ params = {
50
+ "carrier_name": carrier_name,
51
+ "system_only": system_only,
52
+ "limit": limit,
53
+ "offset": offset,
54
+ }
55
+ params = {k: v for k, v in params.items() if v is not None}
56
+ utils.make_get_request(
57
+ "v1/connections", params=params, pretty_print=pretty, line_numbers=line_numbers
58
+ )
59
+
60
+ @app.command("retrieve")
61
+ def retrieve_connection(
62
+ connection_id: str,
63
+ pretty: bool = typer.Option(False, "--pretty", "-p", help="Pretty print the output"),
64
+ line_numbers: bool = typer.Option(False, "--line-numbers", "-n", help="Show line numbers in pretty print"),
65
+ ):
66
+ """
67
+ Retrieve a carrier connection by ID.
68
+
69
+ Example:
70
+ ```terminal
71
+ kcli connections retrieve conn_123456789 | jq "{id, carrier_name, test_mode, active}"
72
+ ```
73
+
74
+ Example Output:
75
+ ```json
76
+ {
77
+ "id": "conn_123456789",
78
+ "carrier_name": "ups",
79
+ "test_mode": true,
80
+ "active": true,
81
+ "capabilities": ["rating", "shipping", "tracking"],
82
+ "credentials": {
83
+ "api_key": "YOUR_API_KEY",
84
+ "password": "YOUR_PASSWORD",
85
+ "account_number": "YOUR_ACCOUNT"
86
+ },
87
+ "metadata": {}
88
+ }
89
+ ```
90
+ """
91
+ utils.make_get_request(
92
+ f"v1/connections/{connection_id}", pretty_print=pretty, line_numbers=line_numbers
93
+ )
94
+
95
+ @app.command("create")
96
+ def create_connection(
97
+ property: typing.List[str] = typer.Option(
98
+ [], "--property", "-d", help="Set nested properties (e.g. -d carrier_name=ups -d credentials[api_key]=xxx)"
99
+ ),
100
+ pretty: bool = typer.Option(False, "--pretty", "-p", help="Pretty print the output"),
101
+ line_numbers: bool = typer.Option(False, "--line-numbers", "-n", help="Show line numbers in pretty print"),
102
+ ):
103
+ """
104
+ Create a new carrier connection.
105
+
106
+ Example:
107
+ ```terminal
108
+ kcli connections create \\
109
+ -d carrier_name=ups \\
110
+ -d test_mode=true \\
111
+ -d credentials[api_key]=YOUR_API_KEY \\
112
+ -d credentials[password]=YOUR_PASSWORD \\
113
+ -d credentials[account_number]=YOUR_ACCOUNT | jq "{id, carrier_name, test_mode}"
114
+ ```
115
+
116
+ Example Output:
117
+ ```json
118
+ {
119
+ "id": "conn_123456789",
120
+ "carrier_name": "ups",
121
+ "test_mode": true,
122
+ "active": true,
123
+ "capabilities": ["rating", "shipping", "tracking"],
124
+ "credentials": {
125
+ "api_key": "YOUR_API_KEY",
126
+ "password": "YOUR_PASSWORD",
127
+ "account_number": "YOUR_ACCOUNT"
128
+ }
129
+ }
130
+ ```
131
+ """
132
+ try:
133
+ payload = utils.parse_nested_properties(property)
134
+ except ValueError as e:
135
+ typer.echo(str(e), err=True)
136
+ raise typer.Exit(code=1)
137
+ utils.make_post_request(
138
+ "v1/connections", payload=payload, pretty_print=pretty, line_numbers=line_numbers
139
+ )
140
+
141
+ @app.command("update")
142
+ def update_connection(
143
+ connection_id: str,
144
+ property: typing.List[str] = typer.Option(
145
+ [], "--property", "-d", help="Set nested properties (e.g. -d credentials[api_key]=newvalue)"
146
+ ),
147
+ pretty: bool = typer.Option(False, "--pretty", "-p", help="Pretty print the output"),
148
+ line_numbers: bool = typer.Option(False, "--line-numbers", "-n", help="Show line numbers in pretty print"),
149
+ ):
150
+ """
151
+ Update a carrier connection by ID.
152
+
153
+ Example:
154
+ ```terminal
155
+ kcli connections update conn_123456789 \\
156
+ -d test_mode=false \\
157
+ -d credentials[api_key]=NEW_API_KEY | jq "{id, carrier_name, test_mode}"
158
+ ```
159
+
160
+ Example Output:
161
+ ```json
162
+ {
163
+ "id": "conn_123456789",
164
+ "carrier_name": "ups",
165
+ "test_mode": false,
166
+ "active": true,
167
+ "credentials": {
168
+ "api_key": "NEW_API_KEY",
169
+ "password": "YOUR_PASSWORD",
170
+ "account_number": "YOUR_ACCOUNT"
171
+ }
172
+ }
173
+ ```
174
+ """
175
+ try:
176
+ payload = utils.parse_nested_properties(property)
177
+ except ValueError as e:
178
+ typer.echo(str(e), err=True)
179
+ raise typer.Exit(code=1)
180
+ utils.make_patch_request(
181
+ f"v1/connections/{connection_id}", payload=payload, pretty_print=pretty, line_numbers=line_numbers
182
+ )
183
+
184
+ @app.command("delete")
185
+ def delete_connection(
186
+ connection_id: str,
187
+ pretty: bool = typer.Option(False, "--pretty", "-p", help="Pretty print the output"),
188
+ line_numbers: bool = typer.Option(False, "--line-numbers", "-n", help="Show line numbers in pretty print"),
189
+ ):
190
+ """
191
+ Delete a carrier connection by ID.
192
+
193
+ Example:
194
+ ```terminal
195
+ kcli connections delete conn_123456789 | jq "{message: \"Connection deleted successfully\"}"
196
+ ```
197
+
198
+ Example Output:
199
+ ```json
200
+ {
201
+ "message": "Connection deleted successfully"
202
+ }
203
+ ```
204
+ """
205
+ utils.make_delete_request(
206
+ f"v1/connections/{connection_id}", pretty_print=pretty, line_numbers=line_numbers
207
+ )
@@ -0,0 +1,151 @@
1
+ import typer
2
+ import karrio_cli.common.utils as utils
3
+ import typing
4
+ import datetime
5
+
6
+ app = typer.Typer()
7
+
8
+
9
+ @app.command("list")
10
+ def list_events(
11
+ type: typing.Optional[str] = typer.Option(
12
+ None,
13
+ help="Event type (e.g. shipment_created, order_created, tracker_created)",
14
+ autocompletion=lambda: [
15
+ "all",
16
+ "batch_completed",
17
+ "batch_failed",
18
+ "batch_queued",
19
+ "batch_running",
20
+ "order_cancelled",
21
+ "order_created",
22
+ "order_delivered",
23
+ "order_fulfilled",
24
+ "order_updated",
25
+ "shipment_cancelled",
26
+ "shipment_delivery_failed",
27
+ "shipment_fulfilled",
28
+ "shipment_needs_attention",
29
+ "shipment_out_for_delivery",
30
+ "shipment_purchased",
31
+ "tracker_created",
32
+ "tracker_updated",
33
+ ]
34
+ ),
35
+ created_after: typing.Optional[datetime.datetime] = None,
36
+ created_before: typing.Optional[datetime.datetime] = None,
37
+ limit: int = typer.Option(20, help="Number of results to return per page"),
38
+ offset: int = typer.Option(
39
+ 0, help="The initial index from which to return the results"
40
+ ),
41
+ pretty: bool = typer.Option(
42
+ False, "--pretty", "-p", help="Pretty print the output"
43
+ ),
44
+ line_numbers: bool = typer.Option(
45
+ False, "--line-numbers", "-n", help="Show line numbers in pretty print"
46
+ ),
47
+ ):
48
+ """
49
+ List all events with optional filters and pagination.
50
+
51
+ Examples:
52
+ ```terminal
53
+ # Get all events and display as a table
54
+ kcli events list --limit 10 | jq -r ".events.edges[].node | [.id, .type, .created_at] | @tsv" | column -t -s $"\t"
55
+ ```
56
+
57
+ ```terminal
58
+ # Get events of a specific type
59
+ kcli events list --type shipment_purchased --limit 5 | jq ".events.edges[].node | {id, type, created_at, data}"
60
+ ```
61
+
62
+ Example Output:
63
+ ```json
64
+ {
65
+ "events": {
66
+ "edges": [
67
+ {
68
+ "node": {
69
+ "id": "evt_123456789",
70
+ "type": "shipment_purchased",
71
+ "data": {
72
+ "shipment_id": "shp_123456789",
73
+ "status": "purchased"
74
+ },
75
+ "test_mode": false,
76
+ "pending_webhooks": 0,
77
+ "created_at": "2024-03-20T10:30:00Z"
78
+ }
79
+ }
80
+ ],
81
+ "page_info": {
82
+ "count": 1,
83
+ "has_next_page": false,
84
+ "has_previous_page": false,
85
+ "start_cursor": "YXJyYXljb25uZWN0aW9uOjA=",
86
+ "end_cursor": "YXJyYXljb25uZWN0aW9uOjA="
87
+ }
88
+ }
89
+ }
90
+ ```
91
+ """
92
+ params = {
93
+ "type": [type] if type else None,
94
+ "created_after": created_after.isoformat() if created_after else None,
95
+ "created_before": created_before.isoformat() if created_before else None,
96
+ "first": limit,
97
+ "offset": offset,
98
+ }
99
+
100
+ # Remove None values from params
101
+ params = {k: v for k, v in params.items() if v is not None}
102
+
103
+ utils.make_graphql_request(
104
+ "get_events",
105
+ {"filter": params},
106
+ pretty_print=pretty,
107
+ line_numbers=line_numbers
108
+ )
109
+
110
+
111
+ @app.command("retrieve")
112
+ def retrieve_event(
113
+ event_id: str,
114
+ pretty: bool = typer.Option(
115
+ False, "--pretty", "-p", help="Pretty print the output"
116
+ ),
117
+ line_numbers: bool = typer.Option(
118
+ False, "--line-numbers", "-n", help="Show line numbers in pretty print"
119
+ ),
120
+ ):
121
+ """
122
+ Retrieve an event by ID.
123
+
124
+ Example:
125
+ ```terminal
126
+ kcli events retrieve evt_123456789 | jq "{id, type, created_at, data}"
127
+ ```
128
+
129
+ Example Output:
130
+ ```json
131
+ {
132
+ "event": {
133
+ "id": "evt_123456789",
134
+ "type": "shipment_purchased",
135
+ "data": {
136
+ "shipment_id": "shp_123456789",
137
+ "status": "purchased"
138
+ },
139
+ "test_mode": false,
140
+ "pending_webhooks": 0,
141
+ "created_at": "2024-03-20T10:30:00Z"
142
+ }
143
+ }
144
+ ```
145
+ """
146
+ utils.make_graphql_request(
147
+ "get_event",
148
+ {"id": event_id},
149
+ pretty_print=pretty,
150
+ line_numbers=line_numbers
151
+ )
@@ -0,0 +1,151 @@
1
+ import typer
2
+ import karrio_cli.common.utils as utils
3
+ import typing
4
+ import datetime
5
+
6
+ app = typer.Typer()
7
+
8
+
9
+ @app.command("list")
10
+ def list_logs(
11
+ entity_id: typing.Optional[str] = None,
12
+ method: typing.Optional[str] = None,
13
+ status_code: typing.Optional[str] = None,
14
+ created_after: typing.Optional[datetime.datetime] = None,
15
+ created_before: typing.Optional[datetime.datetime] = None,
16
+ limit: int = typer.Option(20, help="Number of results to return per page"),
17
+ offset: int = typer.Option(
18
+ 0, help="The initial index from which to return the results"
19
+ ),
20
+ pretty: bool = typer.Option(
21
+ False, "--pretty", "-p", help="Pretty print the output"
22
+ ),
23
+ line_numbers: bool = typer.Option(
24
+ False, "--line-numbers", "-n", help="Show line numbers in pretty print"
25
+ ),
26
+ ):
27
+ """
28
+ List all logs with optional filters and pagination.
29
+
30
+ Examples:
31
+ ```terminal
32
+ # Get all logs and display as a table
33
+ kcli logs list --limit 10 | jq -r ".logs.edges[].node | [.id, .method, .status_code, .path] | @tsv" | column -t -s $"\t"
34
+ ```
35
+
36
+ ```terminal
37
+ # Get logs for a specific entity
38
+ kcli logs list --entity-id shp_123456789 --limit 5 | jq ".logs.edges[].node | {id, method, status_code, path}"
39
+ ```
40
+
41
+ Example Output:
42
+ ```json
43
+ {
44
+ "logs": {
45
+ "edges": [
46
+ {
47
+ "node": {
48
+ "id": "123",
49
+ "method": "POST",
50
+ "status_code": 200,
51
+ "path": "/v1/shipments",
52
+ "request": {
53
+ "headers": {},
54
+ "body": {}
55
+ },
56
+ "response": {
57
+ "headers": {},
58
+ "body": {}
59
+ },
60
+ "response_ms": 245,
61
+ "requested_at": "2024-03-20T10:30:00Z"
62
+ }
63
+ }
64
+ ],
65
+ "pageInfo": {
66
+ "hasNextPage": true,
67
+ "hasPreviousPage": false,
68
+ "startCursor": "YXJyYXljb25uZWN0aW9uOjA=",
69
+ "endCursor": "YXJyYXljb25uZWN0aW9uOjk="
70
+ }
71
+ }
72
+ }
73
+ ```
74
+ """
75
+ params = {
76
+ "entity_id": entity_id,
77
+ "method": method,
78
+ "status_code": status_code,
79
+ "created_after": created_after.isoformat() if created_after else None,
80
+ "created_before": created_before.isoformat() if created_before else None,
81
+ "first": limit,
82
+ "offset": offset,
83
+ }
84
+
85
+ # Remove None values from params
86
+ params = {k: v for k, v in params.items() if v is not None}
87
+
88
+ utils.make_graphql_request(
89
+ "get_logs",
90
+ {"filter": params},
91
+ pretty_print=pretty,
92
+ line_numbers=line_numbers
93
+ )
94
+
95
+
96
+ @app.command("retrieve")
97
+ def retrieve_log(
98
+ log_id: str,
99
+ pretty: bool = typer.Option(
100
+ False, "--pretty", "-p", help="Pretty print the output"
101
+ ),
102
+ line_numbers: bool = typer.Option(
103
+ False, "--line-numbers", "-n", help="Show line numbers in pretty print"
104
+ ),
105
+ ):
106
+ """
107
+ Retrieve a log by ID.
108
+
109
+ Example:
110
+ ```terminal
111
+ kcli logs retrieve 123 | jq "{id, method, status_code, path, response_ms, requested_at}"
112
+ ```
113
+
114
+ Example Output:
115
+ ```json
116
+ {
117
+ "log": {
118
+ "id": "123",
119
+ "method": "POST",
120
+ "status_code": 200,
121
+ "path": "/v1/shipments",
122
+ "request": {
123
+ "headers": {
124
+ "Content-Type": "application/json",
125
+ "Authorization": "Token <redacted>"
126
+ },
127
+ "body": {
128
+ "shipment_id": "shp_123456789"
129
+ }
130
+ },
131
+ "response": {
132
+ "headers": {
133
+ "Content-Type": "application/json"
134
+ },
135
+ "body": {
136
+ "id": "shp_123456789",
137
+ "status": "created"
138
+ }
139
+ },
140
+ "response_ms": 245,
141
+ "requested_at": "2024-03-20T10:30:00Z"
142
+ }
143
+ }
144
+ ```
145
+ """
146
+ utils.make_graphql_request(
147
+ "get_log",
148
+ {"id": int(log_id)},
149
+ pretty_print=pretty,
150
+ line_numbers=line_numbers
151
+ )
@@ -0,0 +1,144 @@
1
+ import typer
2
+ import karrio_cli.common.utils as utils
3
+ import typing
4
+ import datetime
5
+
6
+ app = typer.Typer()
7
+
8
+
9
+ @app.command("list")
10
+ def list_orders(
11
+ created_after: typing.Optional[datetime.datetime] = None,
12
+ created_before: typing.Optional[datetime.datetime] = None,
13
+ status: typing.Optional[str] = None,
14
+ reference: typing.Optional[str] = None,
15
+ metadata_key: typing.Optional[str] = None,
16
+ metadata_value: typing.Optional[str] = None,
17
+ limit: int = typer.Option(20, help="Number of results to return per page"),
18
+ offset: int = typer.Option(
19
+ 0, help="The initial index from which to return the results"
20
+ ),
21
+ pretty: bool = typer.Option(
22
+ False, "--pretty", "-p", help="Pretty print the output"
23
+ ),
24
+ line_numbers: bool = typer.Option(
25
+ False, "--line-numbers", "-n", help="Show line numbers in pretty print"
26
+ ),
27
+ ):
28
+ """
29
+ List all orders with optional filters and pagination.
30
+
31
+ Examples:
32
+ ```terminal
33
+ # Get all orders and display as a table
34
+ kcli orders list --limit 15 | jq -r ".results[] | [.id, .status, .created_at, .total_charge.amount] | @tsv" | column -t -s $"\t"
35
+ ```
36
+
37
+ ```terminal
38
+ # Get pending orders and extract specific fields
39
+ kcli orders list --status pending --limit 5 | jq ".results[] | {id, status, created: .created_at, total: .total_charge.amount}"
40
+ ```
41
+
42
+ Example Output:
43
+ ```json
44
+ {
45
+ "count": 15,
46
+ "next": "/v1/orders?limit=15&offset=15",
47
+ "previous": null,
48
+ "results": [
49
+ {
50
+ "id": "ord_123456789",
51
+ "status": "pending",
52
+ "created_at": "2024-03-20T10:30:00Z",
53
+ "total_charge": {
54
+ "amount": 25.50,
55
+ "currency": "USD"
56
+ },
57
+ "line_items": [],
58
+ "metadata": {}
59
+ }
60
+ ]
61
+ }
62
+ ```
63
+ """
64
+ params = {
65
+ "created_after": created_after.isoformat() if created_after else None,
66
+ "created_before": created_before.isoformat() if created_before else None,
67
+ "status": status,
68
+ "reference": reference,
69
+ "metadata_key": metadata_key,
70
+ "metadata_value": metadata_value,
71
+ "limit": limit,
72
+ "offset": offset,
73
+ }
74
+
75
+ # Remove None values from params
76
+ params = {k: v for k, v in params.items() if v is not None}
77
+
78
+ utils.make_get_request(
79
+ "v1/orders", params=params, pretty_print=pretty, line_numbers=line_numbers
80
+ )
81
+
82
+
83
+ @app.command("retrieve")
84
+ def retrieve_order(
85
+ order_id: str,
86
+ pretty: bool = typer.Option(
87
+ False, "--pretty", "-p", help="Pretty print the output"
88
+ ),
89
+ line_numbers: bool = typer.Option(
90
+ False, "--line-numbers", "-n", help="Show line numbers in pretty print"
91
+ ),
92
+ ):
93
+ """
94
+ Retrieve an order by ID.
95
+
96
+ Example:
97
+ ```terminal
98
+ kcli orders retrieve ord_987654321 | jq "{id, status, created: .created_at, total: .total_charge.amount, items: .line_items | length}"
99
+ ```
100
+ """
101
+ utils.make_get_request(
102
+ f"v1/orders/{order_id}", pretty_print=pretty, line_numbers=line_numbers
103
+ )
104
+
105
+
106
+ @app.command("cancel")
107
+ def cancel_order(
108
+ order_id: str,
109
+ property: typing.List[str] = typer.Option(
110
+ [],
111
+ "--property",
112
+ "-d",
113
+ help="Set nested properties (e.g. -d reason=customer_request)",
114
+ ),
115
+ pretty: bool = typer.Option(
116
+ False, "--pretty", "-p", help="Pretty print the output"
117
+ ),
118
+ line_numbers: bool = typer.Option(
119
+ False, "--line-numbers", "-n", help="Show line numbers in pretty print"
120
+ ),
121
+ ):
122
+ """
123
+ Cancel an order.
124
+
125
+ Example:
126
+ ```terminal
127
+ kcli orders cancel ord_987654321 -d reason=customer_request | jq "{id, status, cancel_reason: .cancellation.reason}"
128
+ ```
129
+ """
130
+ payload = {}
131
+
132
+ try:
133
+ nested_properties = utils.parse_nested_properties(property)
134
+ payload.update(nested_properties)
135
+ except ValueError as e:
136
+ typer.echo(str(e), err=True)
137
+ raise typer.Exit(code=1)
138
+
139
+ utils.make_post_request(
140
+ f"v1/orders/{order_id}/cancel",
141
+ payload=payload,
142
+ pretty_print=pretty,
143
+ line_numbers=line_numbers,
144
+ )