robosystems-client 0.2.23__py3-none-any.whl → 0.2.25__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.

Potentially problematic release.


This version of robosystems-client might be problematic. Click here for more details.

Files changed (86) hide show
  1. robosystems_client/api/agent/auto_select_agent.py +4 -1
  2. robosystems_client/api/agent/batch_process_queries.py +4 -1
  3. robosystems_client/api/agent/execute_specific_agent.py +5 -1
  4. robosystems_client/api/agent/get_agent_metadata.py +5 -1
  5. robosystems_client/api/agent/list_agents.py +4 -1
  6. robosystems_client/api/agent/recommend_agent.py +4 -1
  7. robosystems_client/api/backup/create_backup.py +4 -1
  8. robosystems_client/api/backup/get_backup_download_url.py +5 -1
  9. robosystems_client/api/backup/get_backup_stats.py +4 -1
  10. robosystems_client/api/backup/list_backups.py +4 -1
  11. robosystems_client/api/backup/restore_backup.py +5 -1
  12. robosystems_client/api/billing/cancel_org_subscription.py +5 -1
  13. robosystems_client/api/billing/create_portal_session.py +4 -1
  14. robosystems_client/api/billing/get_checkout_status.py +4 -1
  15. robosystems_client/api/billing/get_org_billing_customer.py +4 -1
  16. robosystems_client/api/billing/get_org_subscription.py +5 -1
  17. robosystems_client/api/billing/get_org_upcoming_invoice.py +4 -1
  18. robosystems_client/api/billing/list_org_invoices.py +4 -1
  19. robosystems_client/api/billing/list_org_subscriptions.py +4 -1
  20. robosystems_client/api/connections/create_connection.py +4 -1
  21. robosystems_client/api/connections/create_link_token.py +4 -1
  22. robosystems_client/api/connections/delete_connection.py +5 -1
  23. robosystems_client/api/connections/exchange_link_token.py +4 -1
  24. robosystems_client/api/connections/get_connection.py +5 -1
  25. robosystems_client/api/connections/get_connection_options.py +4 -1
  26. robosystems_client/api/connections/init_o_auth.py +4 -1
  27. robosystems_client/api/connections/list_connections.py +4 -1
  28. robosystems_client/api/connections/oauth_callback.py +5 -1
  29. robosystems_client/api/connections/sync_connection.py +5 -1
  30. robosystems_client/api/credits_/check_credit_balance.py +4 -1
  31. robosystems_client/api/credits_/check_storage_limits.py +4 -1
  32. robosystems_client/api/credits_/get_credit_summary.py +4 -1
  33. robosystems_client/api/credits_/get_storage_usage.py +4 -1
  34. robosystems_client/api/credits_/list_credit_transactions.py +4 -1
  35. robosystems_client/api/files/create_file_upload.py +4 -1
  36. robosystems_client/api/files/delete_file.py +5 -1
  37. robosystems_client/api/files/get_file.py +5 -1
  38. robosystems_client/api/files/list_files.py +4 -1
  39. robosystems_client/api/files/update_file.py +5 -1
  40. robosystems_client/api/graph_health/get_database_health.py +4 -1
  41. robosystems_client/api/graph_info/get_database_info.py +4 -1
  42. robosystems_client/api/graph_limits/get_graph_limits.py +4 -1
  43. robosystems_client/api/graphs/select_graph.py +4 -1
  44. robosystems_client/api/materialize/get_materialization_status.py +4 -1
  45. robosystems_client/api/materialize/materialize_graph.py +4 -1
  46. robosystems_client/api/mcp/call_mcp_tool.py +4 -1
  47. robosystems_client/api/mcp/list_mcp_tools.py +4 -1
  48. robosystems_client/api/operations/cancel_operation.py +4 -1
  49. robosystems_client/api/operations/get_operation_status.py +4 -1
  50. robosystems_client/api/operations/stream_operation_events.py +4 -1
  51. robosystems_client/api/org/get_org.py +4 -1
  52. robosystems_client/api/org/list_org_graphs.py +4 -1
  53. robosystems_client/api/org/update_org.py +4 -1
  54. robosystems_client/api/org_members/invite_org_member.py +4 -1
  55. robosystems_client/api/org_members/list_org_members.py +4 -1
  56. robosystems_client/api/org_members/remove_org_member.py +5 -1
  57. robosystems_client/api/org_members/update_org_member_role.py +5 -1
  58. robosystems_client/api/org_usage/get_org_limits.py +4 -1
  59. robosystems_client/api/org_usage/get_org_usage.py +4 -1
  60. robosystems_client/api/query/execute_cypher_query.py +4 -1
  61. robosystems_client/api/schema/export_graph_schema.py +4 -1
  62. robosystems_client/api/schema/get_graph_schema.py +4 -1
  63. robosystems_client/api/schema/validate_schema.py +4 -1
  64. robosystems_client/api/subgraphs/create_subgraph.py +4 -1
  65. robosystems_client/api/subgraphs/delete_subgraph.py +5 -1
  66. robosystems_client/api/subgraphs/get_subgraph_info.py +5 -1
  67. robosystems_client/api/subgraphs/get_subgraph_quota.py +4 -1
  68. robosystems_client/api/subgraphs/list_subgraphs.py +4 -1
  69. robosystems_client/api/subscriptions/create_repository_subscription.py +4 -1
  70. robosystems_client/api/subscriptions/get_graph_subscription.py +4 -1
  71. robosystems_client/api/subscriptions/upgrade_subscription.py +4 -1
  72. robosystems_client/api/tables/list_tables.py +4 -1
  73. robosystems_client/api/tables/query_tables.py +4 -1
  74. robosystems_client/api/usage/get_graph_metrics.py +4 -1
  75. robosystems_client/api/usage/get_graph_usage_analytics.py +4 -1
  76. robosystems_client/api/user/revoke_user_api_key.py +4 -1
  77. robosystems_client/api/user/update_user_api_key.py +4 -1
  78. robosystems_client/api/views/create_view.py +4 -1
  79. robosystems_client/api/views/save_view.py +4 -1
  80. robosystems_client/extensions/graph_client.py +163 -3
  81. robosystems_client/extensions/query_client.py +17 -0
  82. robosystems_client/models/token_pricing.py +4 -4
  83. {robosystems_client-0.2.23.dist-info → robosystems_client-0.2.25.dist-info}/METADATA +14 -13
  84. {robosystems_client-0.2.23.dist-info → robosystems_client-0.2.25.dist-info}/RECORD +86 -86
  85. {robosystems_client-0.2.23.dist-info → robosystems_client-0.2.25.dist-info}/WHEEL +0 -0
  86. {robosystems_client-0.2.23.dist-info → robosystems_client-0.2.25.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from typing import Any, cast
3
+ from urllib.parse import quote
3
4
 
4
5
  import httpx
5
6
 
@@ -20,7 +21,9 @@ def _get_kwargs(
20
21
 
21
22
  _kwargs: dict[str, Any] = {
22
23
  "method": "put",
23
- "url": f"/v1/graphs/{graph_id}/subscriptions/upgrade",
24
+ "url": "/v1/graphs/{graph_id}/subscriptions/upgrade".format(
25
+ graph_id=quote(str(graph_id), safe=""),
26
+ ),
24
27
  }
25
28
 
26
29
  _kwargs["json"] = body.to_dict()
@@ -1,5 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from typing import Any, cast
3
+ from urllib.parse import quote
3
4
 
4
5
  import httpx
5
6
 
@@ -16,7 +17,9 @@ def _get_kwargs(
16
17
  ) -> dict[str, Any]:
17
18
  _kwargs: dict[str, Any] = {
18
19
  "method": "get",
19
- "url": f"/v1/graphs/{graph_id}/tables",
20
+ "url": "/v1/graphs/{graph_id}/tables".format(
21
+ graph_id=quote(str(graph_id), safe=""),
22
+ ),
20
23
  }
21
24
 
22
25
  return _kwargs
@@ -1,5 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from typing import Any, cast
3
+ from urllib.parse import quote
3
4
 
4
5
  import httpx
5
6
 
@@ -21,7 +22,9 @@ def _get_kwargs(
21
22
 
22
23
  _kwargs: dict[str, Any] = {
23
24
  "method": "post",
24
- "url": f"/v1/graphs/{graph_id}/tables/query",
25
+ "url": "/v1/graphs/{graph_id}/tables/query".format(
26
+ graph_id=quote(str(graph_id), safe=""),
27
+ ),
25
28
  }
26
29
 
27
30
  _kwargs["json"] = body.to_dict()
@@ -1,5 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from typing import Any
3
+ from urllib.parse import quote
3
4
 
4
5
  import httpx
5
6
 
@@ -16,7 +17,9 @@ def _get_kwargs(
16
17
  ) -> dict[str, Any]:
17
18
  _kwargs: dict[str, Any] = {
18
19
  "method": "get",
19
- "url": f"/v1/graphs/{graph_id}/analytics",
20
+ "url": "/v1/graphs/{graph_id}/analytics".format(
21
+ graph_id=quote(str(graph_id), safe=""),
22
+ ),
20
23
  }
21
24
 
22
25
  return _kwargs
@@ -1,5 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from typing import Any
3
+ from urllib.parse import quote
3
4
 
4
5
  import httpx
5
6
 
@@ -36,7 +37,9 @@ def _get_kwargs(
36
37
 
37
38
  _kwargs: dict[str, Any] = {
38
39
  "method": "get",
39
- "url": f"/v1/graphs/{graph_id}/analytics/usage",
40
+ "url": "/v1/graphs/{graph_id}/analytics/usage".format(
41
+ graph_id=quote(str(graph_id), safe=""),
42
+ ),
40
43
  "params": params,
41
44
  }
42
45
 
@@ -1,5 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from typing import Any
3
+ from urllib.parse import quote
3
4
 
4
5
  import httpx
5
6
 
@@ -16,7 +17,9 @@ def _get_kwargs(
16
17
  ) -> dict[str, Any]:
17
18
  _kwargs: dict[str, Any] = {
18
19
  "method": "delete",
19
- "url": f"/v1/user/api-keys/{api_key_id}",
20
+ "url": "/v1/user/api-keys/{api_key_id}".format(
21
+ api_key_id=quote(str(api_key_id), safe=""),
22
+ ),
20
23
  }
21
24
 
22
25
  return _kwargs
@@ -1,5 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from typing import Any
3
+ from urllib.parse import quote
3
4
 
4
5
  import httpx
5
6
 
@@ -20,7 +21,9 @@ def _get_kwargs(
20
21
 
21
22
  _kwargs: dict[str, Any] = {
22
23
  "method": "put",
23
- "url": f"/v1/user/api-keys/{api_key_id}",
24
+ "url": "/v1/user/api-keys/{api_key_id}".format(
25
+ api_key_id=quote(str(api_key_id), safe=""),
26
+ ),
24
27
  }
25
28
 
26
29
  _kwargs["json"] = body.to_dict()
@@ -1,5 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from typing import Any
3
+ from urllib.parse import quote
3
4
 
4
5
  import httpx
5
6
 
@@ -19,7 +20,9 @@ def _get_kwargs(
19
20
 
20
21
  _kwargs: dict[str, Any] = {
21
22
  "method": "post",
22
- "url": f"/v1/graphs/{graph_id}/views",
23
+ "url": "/v1/graphs/{graph_id}/views".format(
24
+ graph_id=quote(str(graph_id), safe=""),
25
+ ),
23
26
  }
24
27
 
25
28
  _kwargs["json"] = body.to_dict()
@@ -1,5 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from typing import Any
3
+ from urllib.parse import quote
3
4
 
4
5
  import httpx
5
6
 
@@ -20,7 +21,9 @@ def _get_kwargs(
20
21
 
21
22
  _kwargs: dict[str, Any] = {
22
23
  "method": "post",
23
- "url": f"/v1/graphs/{graph_id}/views/save",
24
+ "url": "/v1/graphs/{graph_id}/views/save".format(
25
+ graph_id=quote(str(graph_id), safe=""),
26
+ ),
24
27
  }
25
28
 
26
29
  _kwargs["json"] = body.to_dict()
@@ -1,13 +1,17 @@
1
1
  """Graph Management Client
2
2
 
3
3
  Provides high-level graph management operations with automatic operation monitoring.
4
+ Supports both SSE (Server-Sent Events) for real-time updates and polling fallback.
4
5
  """
5
6
 
6
7
  from dataclasses import dataclass
7
8
  from typing import Dict, Any, Optional, Callable
8
9
  import time
10
+ import json
9
11
  import logging
10
12
 
13
+ import httpx
14
+
11
15
  logger = logging.getLogger(__name__)
12
16
 
13
17
 
@@ -62,10 +66,14 @@ class GraphClient:
62
66
  timeout: int = 60,
63
67
  poll_interval: int = 2,
64
68
  on_progress: Optional[Callable[[str], None]] = None,
69
+ use_sse: bool = True,
65
70
  ) -> str:
66
71
  """
67
72
  Create a graph and wait for completion.
68
73
 
74
+ Uses SSE (Server-Sent Events) for real-time progress updates with
75
+ automatic fallback to polling if SSE connection fails.
76
+
69
77
  Args:
70
78
  metadata: Graph metadata
71
79
  initial_entity: Optional initial entity data
@@ -73,8 +81,9 @@ class GraphClient:
73
81
  Only applies when initial_entity is provided. Set to False to create
74
82
  graph without populating entity data (useful for file-based ingestion).
75
83
  timeout: Maximum time to wait in seconds
76
- poll_interval: Time between status checks in seconds
84
+ poll_interval: Time between status checks in seconds (for polling fallback)
77
85
  on_progress: Callback for progress updates
86
+ use_sse: Whether to try SSE first (default True). Falls back to polling on failure.
78
87
 
79
88
  Returns:
80
89
  graph_id when creation completes
@@ -84,7 +93,6 @@ class GraphClient:
84
93
  """
85
94
  from ..client import AuthenticatedClient
86
95
  from ..api.graphs.create_graph import sync_detailed as create_graph
87
- from ..api.operations.get_operation_status import sync_detailed as get_status
88
96
  from ..models.create_graph_request import CreateGraphRequest
89
97
  from ..models.graph_metadata import GraphMetadata as APIGraphMetadata
90
98
 
@@ -151,13 +159,165 @@ class GraphClient:
151
159
  on_progress(f"Graph created: {graph_id}")
152
160
  return graph_id
153
161
 
154
- # Otherwise, poll operation until complete
162
+ # Otherwise, wait for operation to complete
155
163
  if not operation_id:
156
164
  raise RuntimeError("No graph_id or operation_id in response")
157
165
 
158
166
  if on_progress:
159
167
  on_progress(f"Graph creation queued (operation: {operation_id})")
160
168
 
169
+ # Try SSE first, fall back to polling
170
+ if use_sse:
171
+ try:
172
+ return self._wait_with_sse(operation_id, timeout, on_progress)
173
+ except Exception as e:
174
+ logger.debug(f"SSE connection failed, falling back to polling: {e}")
175
+ if on_progress:
176
+ on_progress("SSE unavailable, using polling...")
177
+
178
+ # Fallback to polling
179
+ return self._wait_with_polling(
180
+ operation_id, timeout, poll_interval, on_progress, client
181
+ )
182
+
183
+ def _wait_with_sse(
184
+ self,
185
+ operation_id: str,
186
+ timeout: int,
187
+ on_progress: Optional[Callable[[str], None]],
188
+ ) -> str:
189
+ """
190
+ Wait for operation completion using SSE stream.
191
+
192
+ Args:
193
+ operation_id: Operation ID to monitor
194
+ timeout: Maximum time to wait in seconds
195
+ on_progress: Callback for progress updates
196
+
197
+ Returns:
198
+ graph_id when operation completes
199
+
200
+ Raises:
201
+ RuntimeError: If operation fails
202
+ TimeoutError: If operation times out
203
+ """
204
+ stream_url = f"{self.base_url}/v1/operations/{operation_id}/stream"
205
+ headers = {"X-API-Key": self.token, "Accept": "text/event-stream"}
206
+
207
+ with httpx.Client(timeout=httpx.Timeout(timeout + 5.0)) as http_client:
208
+ with http_client.stream("GET", stream_url, headers=headers) as response:
209
+ if response.status_code != 200:
210
+ raise RuntimeError(f"SSE connection failed: {response.status_code}")
211
+
212
+ start_time = time.time()
213
+ event_type = None
214
+ event_data = ""
215
+
216
+ for line in response.iter_lines():
217
+ # Check timeout
218
+ if time.time() - start_time > timeout:
219
+ raise TimeoutError(f"Graph creation timed out after {timeout}s")
220
+
221
+ line = line.strip()
222
+
223
+ if not line:
224
+ # Empty line = end of event, process it
225
+ if event_type and event_data:
226
+ result = self._process_sse_event(event_type, event_data, on_progress)
227
+ if result is not None:
228
+ return result
229
+ event_type = None
230
+ event_data = ""
231
+ continue
232
+
233
+ if line.startswith("event:"):
234
+ event_type = line[6:].strip()
235
+ elif line.startswith("data:"):
236
+ event_data = line[5:].strip()
237
+ # Ignore other lines (comments, id, retry, etc.)
238
+
239
+ raise TimeoutError(f"SSE stream ended without completion after {timeout}s")
240
+
241
+ def _process_sse_event(
242
+ self,
243
+ event_type: str,
244
+ event_data: str,
245
+ on_progress: Optional[Callable[[str], None]],
246
+ ) -> Optional[str]:
247
+ """
248
+ Process a single SSE event.
249
+
250
+ Returns:
251
+ graph_id if operation completed, None to continue waiting
252
+
253
+ Raises:
254
+ RuntimeError: If operation failed
255
+ """
256
+ try:
257
+ data = json.loads(event_data)
258
+ except json.JSONDecodeError:
259
+ logger.debug(f"Failed to parse SSE event data: {event_data}")
260
+ return None
261
+
262
+ if event_type == "operation_progress":
263
+ if on_progress:
264
+ message = data.get("message", "Processing...")
265
+ percent = data.get("progress_percent")
266
+ if percent is not None:
267
+ on_progress(f"{message} ({percent:.0f}%)")
268
+ else:
269
+ on_progress(message)
270
+ return None
271
+
272
+ elif event_type == "operation_completed":
273
+ result = data.get("result", {})
274
+ graph_id = result.get("graph_id") if isinstance(result, dict) else None
275
+
276
+ if graph_id:
277
+ if on_progress:
278
+ on_progress(f"Graph created: {graph_id}")
279
+ return graph_id
280
+ else:
281
+ raise RuntimeError("Operation completed but no graph_id in result")
282
+
283
+ elif event_type == "operation_error":
284
+ error = data.get("error", "Unknown error")
285
+ raise RuntimeError(f"Graph creation failed: {error}")
286
+
287
+ elif event_type == "operation_cancelled":
288
+ reason = data.get("reason", "Operation was cancelled")
289
+ raise RuntimeError(f"Graph creation cancelled: {reason}")
290
+
291
+ # Ignore other event types (keepalive, etc.)
292
+ return None
293
+
294
+ def _wait_with_polling(
295
+ self,
296
+ operation_id: str,
297
+ timeout: int,
298
+ poll_interval: int,
299
+ on_progress: Optional[Callable[[str], None]],
300
+ client: Any,
301
+ ) -> str:
302
+ """
303
+ Wait for operation completion using polling.
304
+
305
+ Args:
306
+ operation_id: Operation ID to monitor
307
+ timeout: Maximum time to wait in seconds
308
+ poll_interval: Time between status checks
309
+ on_progress: Callback for progress updates
310
+ client: Authenticated HTTP client
311
+
312
+ Returns:
313
+ graph_id when operation completes
314
+
315
+ Raises:
316
+ RuntimeError: If operation fails
317
+ TimeoutError: If operation times out
318
+ """
319
+ from ..api.operations.get_operation_status import sync_detailed as get_status
320
+
161
321
  max_attempts = timeout // poll_interval
162
322
  for attempt in range(max_attempts):
163
323
  time.sleep(poll_interval)
@@ -266,6 +266,23 @@ class QueryClient:
266
266
  else:
267
267
  raise Exception(f"Query execution failed: {error_msg}")
268
268
 
269
+ # Handle error responses (4xx/5xx) where parsed is None
270
+ if hasattr(response, "status_code") and response.status_code >= 400:
271
+ import json as _json
272
+
273
+ detail = f"HTTP {response.status_code}"
274
+ try:
275
+ body = (
276
+ response.content.decode("utf-8")
277
+ if isinstance(response.content, bytes)
278
+ else str(response.content)
279
+ )
280
+ error_data = _json.loads(body)
281
+ detail = error_data.get("detail", error_data.get("message", body))
282
+ except Exception:
283
+ pass
284
+ raise Exception(f"Query failed ({response.status_code}): {detail}")
285
+
269
286
  # Unexpected response format
270
287
  raise Exception("Unexpected response format from query endpoint")
271
288
 
@@ -14,12 +14,12 @@ class TokenPricing:
14
14
  """AI token pricing for a specific model.
15
15
 
16
16
  Attributes:
17
- input_per_1k_tokens (int): Credits per 1K input tokens
18
- output_per_1k_tokens (int): Credits per 1K output tokens
17
+ input_per_1k_tokens (float): Credits per 1K input tokens
18
+ output_per_1k_tokens (float): Credits per 1K output tokens
19
19
  """
20
20
 
21
- input_per_1k_tokens: int
22
- output_per_1k_tokens: int
21
+ input_per_1k_tokens: float
22
+ output_per_1k_tokens: float
23
23
  additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
24
24
 
25
25
  def to_dict(self) -> dict[str, Any]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robosystems-client
3
- Version: 0.2.23
3
+ Version: 0.2.25
4
4
  Summary: Python Client for RoboSystems financial graph database API
5
5
  Author: RFS LLC
6
6
  License: MIT
@@ -33,8 +33,8 @@ Requires-Dist: pydantic>=2.11.7
33
33
  Requires-Dist: python-dateutil>=2.8.0
34
34
  Requires-Dist: typing-extensions>=4.0.0
35
35
  Provides-Extra: all
36
- Requires-Dist: pandas>=1.5.0; extra == 'all'
37
- Requires-Dist: pyarrow>=10.0.0; extra == 'all'
36
+ Requires-Dist: pandas>=2.1.0; extra == 'all'
37
+ Requires-Dist: pyarrow>=17.0.0; extra == 'all'
38
38
  Provides-Extra: dev
39
39
  Requires-Dist: basedpyright>=1.21.0; extra == 'dev'
40
40
  Requires-Dist: build>=1.0.0; extra == 'dev'
@@ -45,11 +45,11 @@ Requires-Dist: pytest>=8.3.5; extra == 'dev'
45
45
  Requires-Dist: ruff>=0.12; extra == 'dev'
46
46
  Requires-Dist: twine>=5.0.0; extra == 'dev'
47
47
  Provides-Extra: extensions
48
- Requires-Dist: pandas>=1.5.0; extra == 'extensions'
49
- Requires-Dist: pyarrow>=10.0.0; extra == 'extensions'
48
+ Requires-Dist: pandas>=2.1.0; extra == 'extensions'
49
+ Requires-Dist: pyarrow>=17.0.0; extra == 'extensions'
50
50
  Provides-Extra: tables
51
- Requires-Dist: pandas>=1.5.0; extra == 'tables'
52
- Requires-Dist: pyarrow>=10.0.0; extra == 'tables'
51
+ Requires-Dist: pandas>=2.1.0; extra == 'tables'
52
+ Requires-Dist: pyarrow>=17.0.0; extra == 'tables'
53
53
  Description-Content-Type: text/markdown
54
54
 
55
55
  # RoboSystems Python Client
@@ -81,18 +81,19 @@ pip install robosystems-client[tables]
81
81
  pip install robosystems-client[all]
82
82
  ```
83
83
 
84
- ## API Reference
84
+ ## Resources
85
85
 
86
- - [API reference](https://api.robosystems.ai)
87
- - [API documentation](https://api.robosystems.ai/docs)
88
- - [OpenAPI specification](https://api.robosystems.ai/openapi.json)
86
+ - [RoboSystems Platform](https://robosystems.ai)
87
+ - [GitHub Repository](https://github.com/RoboFinSystems/robosystems)
88
+ - [API Documentation](https://api.robosystems.ai/docs)
89
+ - [OpenAPI Specification](https://api.robosystems.ai/openapi.json)
89
90
 
90
91
  ## Support
91
92
 
92
93
  - [Issues](https://github.com/RoboFinSystems/robosystems-python-client/issues)
93
- - [Discussions](https://github.com/RoboFinSystems/robosystems/discussions)
94
- - [Projects](https://github.com/RoboFinSystems/robosystems/projects)
95
94
  - [Wiki](https://github.com/RoboFinSystems/robosystems/wiki)
95
+ - [Projects](https://github.com/orgs/RoboFinSystems/projects)
96
+ - [Discussions](https://github.com/orgs/RoboFinSystems/discussions)
96
97
 
97
98
  ## License
98
99