bytekit-sdk 0.3.0__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 (227) hide show
  1. bytekit/__init__.py +8 -0
  2. bytekit/api/__init__.py +1 -0
  3. bytekit/api/account/__init__.py +1 -0
  4. bytekit/api/account/get_account.py +157 -0
  5. bytekit/api/bulk/__init__.py +1 -0
  6. bytekit/api/bulk/create_bulk.py +204 -0
  7. bytekit/api/bulk/delete_bulk.py +177 -0
  8. bytekit/api/bulk/get_bulk.py +157 -0
  9. bytekit/api/bulk/list_bulk_screenshots.py +152 -0
  10. bytekit/api/fetch/__init__.py +1 -0
  11. bytekit/api/fetch/get_fetch.py +254 -0
  12. bytekit/api/fetch/post_fetch.py +178 -0
  13. bytekit/api/fetch_bulk/__init__.py +1 -0
  14. bytekit/api/fetch_bulk/create_fetch_bulk.py +180 -0
  15. bytekit/api/fetch_bulk/get_fetch_bulk.py +157 -0
  16. bytekit/api/monitors/__init__.py +1 -0
  17. bytekit/api/monitors/create_monitor.py +180 -0
  18. bytekit/api/monitors/delete_monitor.py +155 -0
  19. bytekit/api/monitors/get_monitor.py +157 -0
  20. bytekit/api/monitors/list_monitor_captures.py +188 -0
  21. bytekit/api/monitors/list_monitors.py +193 -0
  22. bytekit/api/monitors/update_monitor.py +191 -0
  23. bytekit/api/scrape/__init__.py +1 -0
  24. bytekit/api/scrape/create_scrape.py +197 -0
  25. bytekit/api/scrape/get_scrape.py +231 -0
  26. bytekit/api/scrape_bulk/__init__.py +1 -0
  27. bytekit/api/scrape_bulk/create_scrape_bulk.py +188 -0
  28. bytekit/api/scrape_bulk/get_scrape_bulk.py +157 -0
  29. bytekit/api/screenshots/__init__.py +1 -0
  30. bytekit/api/screenshots/create_screenshot.py +208 -0
  31. bytekit/api/screenshots/get_screenshot.py +177 -0
  32. bytekit/api/search/__init__.py +1 -0
  33. bytekit/api/search/create_search.py +225 -0
  34. bytekit/api/sitemap/__init__.py +1 -0
  35. bytekit/api/sitemap/create_sitemap.py +192 -0
  36. bytekit/api/sitemap/get_sitemap.py +157 -0
  37. bytekit/api/usage/__init__.py +1 -0
  38. bytekit/api/usage/get_usage.py +126 -0
  39. bytekit/api/usage/get_usage_by_endpoint.py +215 -0
  40. bytekit/api/usage/get_usage_daily.py +203 -0
  41. bytekit/api/webhooks/__init__.py +1 -0
  42. bytekit/api/webhooks/list_webhook_deliveries.py +214 -0
  43. bytekit/api/webhooks/retry_webhook_delivery.py +165 -0
  44. bytekit/client.py +418 -0
  45. bytekit/errors.py +18 -0
  46. bytekit/models/__init__.py +401 -0
  47. bytekit/models/account_bearer_response.py +207 -0
  48. bytekit/models/account_bearer_response_api_key.py +134 -0
  49. bytekit/models/account_bearer_response_api_key_environment.py +8 -0
  50. bytekit/models/account_bearer_response_auto_topup.py +83 -0
  51. bytekit/models/account_bearer_response_plan.py +150 -0
  52. bytekit/models/account_bearer_response_subscription.py +85 -0
  53. bytekit/models/account_bearer_response_subscription_plan.py +99 -0
  54. bytekit/models/account_bearer_response_subscription_status.py +10 -0
  55. bytekit/models/account_session_response.py +164 -0
  56. bytekit/models/account_session_response_notifications.py +51 -0
  57. bytekit/models/account_session_response_plan.py +150 -0
  58. bytekit/models/bandwidth_balance.py +91 -0
  59. bytekit/models/capture_response.py +216 -0
  60. bytekit/models/capture_response_outcome.py +10 -0
  61. bytekit/models/clip.py +83 -0
  62. bytekit/models/cookie.py +90 -0
  63. bytekit/models/create_bulk_body.py +155 -0
  64. bytekit/models/create_bulk_body_defaults.py +423 -0
  65. bytekit/models/create_bulk_body_defaults_device.py +9 -0
  66. bytekit/models/create_bulk_body_defaults_device_scale_factor_type_1.py +9 -0
  67. bytekit/models/create_bulk_body_defaults_device_scale_factor_type_2_type_1.py +9 -0
  68. bytekit/models/create_bulk_body_defaults_device_scale_factor_type_3_type_1.py +9 -0
  69. bytekit/models/create_bulk_body_defaults_formats_item.py +12 -0
  70. bytekit/models/create_bulk_body_defaults_type.py +9 -0
  71. bytekit/models/create_bulk_body_defaults_viewport_type_0.py +67 -0
  72. bytekit/models/create_bulk_body_defaults_wait_until.py +10 -0
  73. bytekit/models/create_bulk_body_items_item.py +380 -0
  74. bytekit/models/create_bulk_body_items_item_device.py +9 -0
  75. bytekit/models/create_bulk_body_items_item_formats_item.py +12 -0
  76. bytekit/models/create_bulk_body_items_item_scenario.py +10 -0
  77. bytekit/models/create_bulk_body_items_item_type.py +9 -0
  78. bytekit/models/create_bulk_body_items_item_viewport_type_0.py +67 -0
  79. bytekit/models/create_bulk_body_items_item_wait_until.py +10 -0
  80. bytekit/models/create_bulk_response_202.py +164 -0
  81. bytekit/models/create_bulk_response_202_status.py +10 -0
  82. bytekit/models/create_fetch_bulk_body.py +161 -0
  83. bytekit/models/create_fetch_bulk_body_defaults.py +91 -0
  84. bytekit/models/create_fetch_bulk_body_defaults_format.py +9 -0
  85. bytekit/models/create_fetch_bulk_body_metadata.py +44 -0
  86. bytekit/models/create_fetch_bulk_body_urls_item_type_1.py +102 -0
  87. bytekit/models/create_fetch_bulk_body_urls_item_type_1_format.py +9 -0
  88. bytekit/models/create_fetch_bulk_response_202.py +44 -0
  89. bytekit/models/create_scrape_bulk_body.py +179 -0
  90. bytekit/models/create_scrape_bulk_body_custom.py +52 -0
  91. bytekit/models/create_scrape_bulk_body_defaults.py +167 -0
  92. bytekit/models/create_scrape_bulk_body_defaults_formats_item.py +12 -0
  93. bytekit/models/create_scrape_bulk_body_defaults_headers.py +44 -0
  94. bytekit/models/create_scrape_bulk_body_items_item.py +226 -0
  95. bytekit/models/create_scrape_bulk_body_items_item_custom.py +50 -0
  96. bytekit/models/create_scrape_bulk_body_items_item_formats_item.py +12 -0
  97. bytekit/models/create_scrape_bulk_body_items_item_headers.py +44 -0
  98. bytekit/models/create_scrape_bulk_body_items_item_metadata.py +44 -0
  99. bytekit/models/create_scrape_bulk_response_202.py +166 -0
  100. bytekit/models/create_scrape_bulk_response_202_status.py +10 -0
  101. bytekit/models/create_search_body.py +140 -0
  102. bytekit/models/create_search_body_date_range.py +13 -0
  103. bytekit/models/create_search_body_type.py +10 -0
  104. bytekit/models/create_search_response_200.py +119 -0
  105. bytekit/models/create_search_response_200_results_item.py +161 -0
  106. bytekit/models/create_search_response_200_results_item_image.py +113 -0
  107. bytekit/models/create_search_response_502.py +46 -0
  108. bytekit/models/create_search_response_502_error.py +8 -0
  109. bytekit/models/credit_balance.py +91 -0
  110. bytekit/models/delete_bulk_response_200.py +164 -0
  111. bytekit/models/delete_bulk_response_200_status.py +11 -0
  112. bytekit/models/error.py +83 -0
  113. bytekit/models/error_error.py +100 -0
  114. bytekit/models/error_status.py +8 -0
  115. bytekit/models/fetch_request.py +276 -0
  116. bytekit/models/fetch_request_cache_ttl_type_1.py +8 -0
  117. bytekit/models/fetch_request_custom.py +48 -0
  118. bytekit/models/fetch_request_format.py +9 -0
  119. bytekit/models/fetch_request_markdown_images.py +11 -0
  120. bytekit/models/fetch_request_markdown_links.py +11 -0
  121. bytekit/models/fetch_request_markdown_mode.py +10 -0
  122. bytekit/models/get_bulk_response_200.py +164 -0
  123. bytekit/models/get_bulk_response_200_status.py +11 -0
  124. bytekit/models/get_fetch_bulk_response_200.py +44 -0
  125. bytekit/models/get_fetch_cache_ttl_type_1.py +8 -0
  126. bytekit/models/get_fetch_format.py +9 -0
  127. bytekit/models/get_scrape_bulk_response_200.py +164 -0
  128. bytekit/models/get_scrape_bulk_response_200_status.py +11 -0
  129. bytekit/models/get_usage_by_endpoint_response_200.py +114 -0
  130. bytekit/models/get_usage_by_endpoint_response_200_rows_item.py +90 -0
  131. bytekit/models/get_usage_by_endpoint_response_200_rows_item_endpoint.py +17 -0
  132. bytekit/models/get_usage_by_endpoint_response_200_totals.py +67 -0
  133. bytekit/models/get_usage_daily_response_200.py +97 -0
  134. bytekit/models/get_usage_daily_response_200_data_item.py +219 -0
  135. bytekit/models/get_usage_response_200.py +344 -0
  136. bytekit/models/get_usage_response_200_plan_type.py +10 -0
  137. bytekit/models/list_bulk_screenshots_response_200.py +44 -0
  138. bytekit/models/list_monitor_captures_response_200.py +101 -0
  139. bytekit/models/list_monitors_response_200.py +101 -0
  140. bytekit/models/list_monitors_status.py +12 -0
  141. bytekit/models/list_webhook_deliveries_response_200.py +101 -0
  142. bytekit/models/list_webhook_deliveries_status.py +11 -0
  143. bytekit/models/metadata.py +44 -0
  144. bytekit/models/monitor_create_request.py +219 -0
  145. bytekit/models/monitor_create_request_interval_type.py +11 -0
  146. bytekit/models/monitor_create_request_notify_on.py +9 -0
  147. bytekit/models/monitor_create_request_options.py +44 -0
  148. bytekit/models/monitor_create_request_scrape_options.py +44 -0
  149. bytekit/models/monitor_create_request_type.py +9 -0
  150. bytekit/models/monitor_create_request_webhook_headers.py +44 -0
  151. bytekit/models/monitor_create_response.py +423 -0
  152. bytekit/models/monitor_response.py +411 -0
  153. bytekit/models/monitor_response_interval_type.py +11 -0
  154. bytekit/models/monitor_response_metadata_type_0.py +44 -0
  155. bytekit/models/monitor_response_status.py +12 -0
  156. bytekit/models/monitor_response_type.py +9 -0
  157. bytekit/models/monitor_response_webhook_headers_type_0.py +44 -0
  158. bytekit/models/monitor_update_request.py +223 -0
  159. bytekit/models/monitor_update_request_interval_type.py +11 -0
  160. bytekit/models/monitor_update_request_notify_on.py +9 -0
  161. bytekit/models/monitor_update_request_options.py +44 -0
  162. bytekit/models/monitor_update_request_scrape_options.py +44 -0
  163. bytekit/models/monitor_update_request_status.py +9 -0
  164. bytekit/models/monitor_update_request_webhook_headers.py +44 -0
  165. bytekit/models/scrape_error_envelope.py +113 -0
  166. bytekit/models/scrape_error_envelope_error.py +93 -0
  167. bytekit/models/scrape_error_envelope_error_code.py +18 -0
  168. bytekit/models/scrape_error_envelope_schema_version.py +8 -0
  169. bytekit/models/scrape_error_envelope_status.py +8 -0
  170. bytekit/models/scrape_formats.py +183 -0
  171. bytekit/models/scrape_markdown_tokens.py +75 -0
  172. bytekit/models/scrape_metadata.py +262 -0
  173. bytekit/models/scrape_queued_envelope.py +124 -0
  174. bytekit/models/scrape_queued_envelope_schema_version.py +8 -0
  175. bytekit/models/scrape_queued_envelope_status.py +8 -0
  176. bytekit/models/scrape_request.py +485 -0
  177. bytekit/models/scrape_request_cache_ttl_type_1.py +8 -0
  178. bytekit/models/scrape_request_custom.py +48 -0
  179. bytekit/models/scrape_request_events_item.py +10 -0
  180. bytekit/models/scrape_request_formats_item.py +12 -0
  181. bytekit/models/scrape_request_headers.py +44 -0
  182. bytekit/models/scrape_request_markdown_images.py +11 -0
  183. bytekit/models/scrape_request_markdown_links.py +11 -0
  184. bytekit/models/scrape_request_markdown_mode.py +10 -0
  185. bytekit/models/scrape_request_token_encoding.py +9 -0
  186. bytekit/models/scrape_request_x_internal_scrape_path.py +8 -0
  187. bytekit/models/scrape_scored_image.py +128 -0
  188. bytekit/models/scrape_scored_link.py +94 -0
  189. bytekit/models/scrape_stats.py +75 -0
  190. bytekit/models/scrape_success_envelope.py +345 -0
  191. bytekit/models/scrape_success_envelope_cache.py +10 -0
  192. bytekit/models/scrape_success_envelope_custom.py +48 -0
  193. bytekit/models/scrape_success_envelope_schema_version.py +8 -0
  194. bytekit/models/scrape_success_envelope_status.py +8 -0
  195. bytekit/models/scrape_table.py +96 -0
  196. bytekit/models/scrape_table_kind.py +10 -0
  197. bytekit/models/scrape_warning.py +88 -0
  198. bytekit/models/scrape_warning_code.py +17 -0
  199. bytekit/models/screenshot_request.py +445 -0
  200. bytekit/models/screenshot_request_device.py +9 -0
  201. bytekit/models/screenshot_request_device_scale_factor_type_1.py +9 -0
  202. bytekit/models/screenshot_request_device_scale_factor_type_2_type_1.py +9 -0
  203. bytekit/models/screenshot_request_device_scale_factor_type_3_type_1.py +9 -0
  204. bytekit/models/screenshot_request_format.py +9 -0
  205. bytekit/models/screenshot_request_headers.py +44 -0
  206. bytekit/models/screenshot_request_wait_until.py +10 -0
  207. bytekit/models/screenshot_response.py +264 -0
  208. bytekit/models/screenshot_response_status.py +11 -0
  209. bytekit/models/sitemap_request.py +210 -0
  210. bytekit/models/sitemap_request_process_type_0.py +90 -0
  211. bytekit/models/sitemap_request_process_type_0_options.py +44 -0
  212. bytekit/models/sitemap_request_strategy.py +10 -0
  213. bytekit/models/sitemap_response.py +418 -0
  214. bytekit/models/sitemap_response_cache.py +10 -0
  215. bytekit/models/sitemap_response_metadata_type_0.py +44 -0
  216. bytekit/models/sitemap_response_process_type_0.py +44 -0
  217. bytekit/models/sitemap_response_sources_type_0.py +44 -0
  218. bytekit/models/sitemap_response_status.py +11 -0
  219. bytekit/models/viewport.py +67 -0
  220. bytekit/models/webhook_delivery_response.py +270 -0
  221. bytekit/models/webhook_delivery_response_event_type.py +14 -0
  222. bytekit/models/webhook_delivery_response_status.py +11 -0
  223. bytekit/py.typed +0 -0
  224. bytekit/types.py +54 -0
  225. bytekit_sdk-0.3.0.dist-info/METADATA +141 -0
  226. bytekit_sdk-0.3.0.dist-info/RECORD +227 -0
  227. bytekit_sdk-0.3.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,270 @@
1
+ import datetime
2
+ from collections.abc import Mapping
3
+ from typing import (
4
+ Any,
5
+ TypeVar,
6
+ Union,
7
+ cast,
8
+ )
9
+
10
+ from attrs import define as _attrs_define
11
+ from attrs import field as _attrs_field
12
+ from dateutil.parser import isoparse
13
+
14
+ from ..models.webhook_delivery_response_event_type import (
15
+ WebhookDeliveryResponseEventType,
16
+ )
17
+ from ..models.webhook_delivery_response_status import WebhookDeliveryResponseStatus
18
+
19
+ T = TypeVar("T", bound="WebhookDeliveryResponse")
20
+
21
+
22
+ @_attrs_define
23
+ class WebhookDeliveryResponse:
24
+ """
25
+ Attributes:
26
+ id (str): Example: wh_01j9abc123.
27
+ event_type (WebhookDeliveryResponseEventType): Machine-readable event discriminator. This value is also sent as
28
+ the `X-ByteKit-Event` request header on every outbound webhook delivery, allowing receivers to dispatch on the
29
+ header without parsing the body shape.
30
+ Example: bulk.completed.
31
+ target_url (str):
32
+ status (WebhookDeliveryResponseStatus):
33
+ attempts (int):
34
+ max_attempts (int):
35
+ next_attempt_at (Union[None, datetime.datetime]):
36
+ response_status (Union[None, int]):
37
+ response_ms (Union[None, int]):
38
+ created_at (datetime.datetime):
39
+ delivered_at (Union[None, datetime.datetime]):
40
+ screenshot_id (Union[None, str]):
41
+ recording_id (Union[None, str]):
42
+ bulk_id (Union[None, str]):
43
+ monitor_id (Union[None, str]):
44
+ scrape_id (Union[None, str]):
45
+ """
46
+
47
+ id: str
48
+ event_type: WebhookDeliveryResponseEventType
49
+ target_url: str
50
+ status: WebhookDeliveryResponseStatus
51
+ attempts: int
52
+ max_attempts: int
53
+ next_attempt_at: Union[None, datetime.datetime]
54
+ response_status: Union[None, int]
55
+ response_ms: Union[None, int]
56
+ created_at: datetime.datetime
57
+ delivered_at: Union[None, datetime.datetime]
58
+ screenshot_id: Union[None, str]
59
+ recording_id: Union[None, str]
60
+ bulk_id: Union[None, str]
61
+ monitor_id: Union[None, str]
62
+ scrape_id: Union[None, str]
63
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
64
+
65
+ def to_dict(self) -> dict[str, Any]:
66
+ id = self.id
67
+
68
+ event_type = self.event_type.value
69
+
70
+ target_url = self.target_url
71
+
72
+ status = self.status.value
73
+
74
+ attempts = self.attempts
75
+
76
+ max_attempts = self.max_attempts
77
+
78
+ next_attempt_at: Union[None, str]
79
+ if isinstance(self.next_attempt_at, datetime.datetime):
80
+ next_attempt_at = self.next_attempt_at.isoformat()
81
+ else:
82
+ next_attempt_at = self.next_attempt_at
83
+
84
+ response_status: Union[None, int]
85
+ response_status = self.response_status
86
+
87
+ response_ms: Union[None, int]
88
+ response_ms = self.response_ms
89
+
90
+ created_at = self.created_at.isoformat()
91
+
92
+ delivered_at: Union[None, str]
93
+ if isinstance(self.delivered_at, datetime.datetime):
94
+ delivered_at = self.delivered_at.isoformat()
95
+ else:
96
+ delivered_at = self.delivered_at
97
+
98
+ screenshot_id: Union[None, str]
99
+ screenshot_id = self.screenshot_id
100
+
101
+ recording_id: Union[None, str]
102
+ recording_id = self.recording_id
103
+
104
+ bulk_id: Union[None, str]
105
+ bulk_id = self.bulk_id
106
+
107
+ monitor_id: Union[None, str]
108
+ monitor_id = self.monitor_id
109
+
110
+ scrape_id: Union[None, str]
111
+ scrape_id = self.scrape_id
112
+
113
+ field_dict: dict[str, Any] = {}
114
+ field_dict.update(self.additional_properties)
115
+ field_dict.update(
116
+ {
117
+ "id": id,
118
+ "event_type": event_type,
119
+ "target_url": target_url,
120
+ "status": status,
121
+ "attempts": attempts,
122
+ "max_attempts": max_attempts,
123
+ "next_attempt_at": next_attempt_at,
124
+ "response_status": response_status,
125
+ "response_ms": response_ms,
126
+ "created_at": created_at,
127
+ "delivered_at": delivered_at,
128
+ "screenshot_id": screenshot_id,
129
+ "recording_id": recording_id,
130
+ "bulk_id": bulk_id,
131
+ "monitor_id": monitor_id,
132
+ "scrape_id": scrape_id,
133
+ }
134
+ )
135
+
136
+ return field_dict
137
+
138
+ @classmethod
139
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
140
+ d = dict(src_dict)
141
+ id = d.pop("id")
142
+
143
+ event_type = WebhookDeliveryResponseEventType(d.pop("event_type"))
144
+
145
+ target_url = d.pop("target_url")
146
+
147
+ status = WebhookDeliveryResponseStatus(d.pop("status"))
148
+
149
+ attempts = d.pop("attempts")
150
+
151
+ max_attempts = d.pop("max_attempts")
152
+
153
+ def _parse_next_attempt_at(data: object) -> Union[None, datetime.datetime]:
154
+ if data is None:
155
+ return data
156
+ try:
157
+ if not isinstance(data, str):
158
+ raise TypeError()
159
+ next_attempt_at_type_0 = isoparse(data)
160
+
161
+ return next_attempt_at_type_0
162
+ except: # noqa: E722
163
+ pass
164
+ return cast(Union[None, datetime.datetime], data)
165
+
166
+ next_attempt_at = _parse_next_attempt_at(d.pop("next_attempt_at"))
167
+
168
+ def _parse_response_status(data: object) -> Union[None, int]:
169
+ if data is None:
170
+ return data
171
+ return cast(Union[None, int], data)
172
+
173
+ response_status = _parse_response_status(d.pop("response_status"))
174
+
175
+ def _parse_response_ms(data: object) -> Union[None, int]:
176
+ if data is None:
177
+ return data
178
+ return cast(Union[None, int], data)
179
+
180
+ response_ms = _parse_response_ms(d.pop("response_ms"))
181
+
182
+ created_at = isoparse(d.pop("created_at"))
183
+
184
+ def _parse_delivered_at(data: object) -> Union[None, datetime.datetime]:
185
+ if data is None:
186
+ return data
187
+ try:
188
+ if not isinstance(data, str):
189
+ raise TypeError()
190
+ delivered_at_type_0 = isoparse(data)
191
+
192
+ return delivered_at_type_0
193
+ except: # noqa: E722
194
+ pass
195
+ return cast(Union[None, datetime.datetime], data)
196
+
197
+ delivered_at = _parse_delivered_at(d.pop("delivered_at"))
198
+
199
+ def _parse_screenshot_id(data: object) -> Union[None, str]:
200
+ if data is None:
201
+ return data
202
+ return cast(Union[None, str], data)
203
+
204
+ screenshot_id = _parse_screenshot_id(d.pop("screenshot_id"))
205
+
206
+ def _parse_recording_id(data: object) -> Union[None, str]:
207
+ if data is None:
208
+ return data
209
+ return cast(Union[None, str], data)
210
+
211
+ recording_id = _parse_recording_id(d.pop("recording_id"))
212
+
213
+ def _parse_bulk_id(data: object) -> Union[None, str]:
214
+ if data is None:
215
+ return data
216
+ return cast(Union[None, str], data)
217
+
218
+ bulk_id = _parse_bulk_id(d.pop("bulk_id"))
219
+
220
+ def _parse_monitor_id(data: object) -> Union[None, str]:
221
+ if data is None:
222
+ return data
223
+ return cast(Union[None, str], data)
224
+
225
+ monitor_id = _parse_monitor_id(d.pop("monitor_id"))
226
+
227
+ def _parse_scrape_id(data: object) -> Union[None, str]:
228
+ if data is None:
229
+ return data
230
+ return cast(Union[None, str], data)
231
+
232
+ scrape_id = _parse_scrape_id(d.pop("scrape_id"))
233
+
234
+ webhook_delivery_response = cls(
235
+ id=id,
236
+ event_type=event_type,
237
+ target_url=target_url,
238
+ status=status,
239
+ attempts=attempts,
240
+ max_attempts=max_attempts,
241
+ next_attempt_at=next_attempt_at,
242
+ response_status=response_status,
243
+ response_ms=response_ms,
244
+ created_at=created_at,
245
+ delivered_at=delivered_at,
246
+ screenshot_id=screenshot_id,
247
+ recording_id=recording_id,
248
+ bulk_id=bulk_id,
249
+ monitor_id=monitor_id,
250
+ scrape_id=scrape_id,
251
+ )
252
+
253
+ webhook_delivery_response.additional_properties = d
254
+ return webhook_delivery_response
255
+
256
+ @property
257
+ def additional_keys(self) -> list[str]:
258
+ return list(self.additional_properties.keys())
259
+
260
+ def __getitem__(self, key: str) -> Any:
261
+ return self.additional_properties[key]
262
+
263
+ def __setitem__(self, key: str, value: Any) -> None:
264
+ self.additional_properties[key] = value
265
+
266
+ def __delitem__(self, key: str) -> None:
267
+ del self.additional_properties[key]
268
+
269
+ def __contains__(self, key: str) -> bool:
270
+ return key in self.additional_properties
@@ -0,0 +1,14 @@
1
+ from enum import Enum
2
+
3
+
4
+ class WebhookDeliveryResponseEventType(str, Enum):
5
+ BULK_COMPLETED = "bulk.completed"
6
+ MONITOR_CAPTURED = "monitor.captured"
7
+ MONITOR_CHANGE_DETECTED = "monitor.change_detected"
8
+ SCRAPE_COMPLETED = "scrape.completed"
9
+ SCRAPE_FAILED = "scrape.failed"
10
+ SITEMAP_COMPLETED = "sitemap.completed"
11
+ SITEMAP_FAILED = "sitemap.failed"
12
+
13
+ def __str__(self) -> str:
14
+ return str(self.value)
@@ -0,0 +1,11 @@
1
+ from enum import Enum
2
+
3
+
4
+ class WebhookDeliveryResponseStatus(str, Enum):
5
+ DELIVERED = "delivered"
6
+ EXHAUSTED = "exhausted"
7
+ FAILED = "failed"
8
+ PENDING = "pending"
9
+
10
+ def __str__(self) -> str:
11
+ return str(self.value)
bytekit/py.typed ADDED
File without changes
bytekit/types.py ADDED
@@ -0,0 +1,54 @@
1
+ """Contains some shared types for properties"""
2
+
3
+ from collections.abc import Mapping, MutableMapping
4
+ from http import HTTPStatus
5
+ from typing import IO, BinaryIO, Generic, Literal, Optional, TypeVar, Union
6
+
7
+ from attrs import define
8
+
9
+
10
+ class Unset:
11
+ def __bool__(self) -> Literal[False]:
12
+ return False
13
+
14
+
15
+ UNSET: Unset = Unset()
16
+
17
+ # The types that `httpx.Client(files=)` can accept, copied from that library.
18
+ FileContent = Union[IO[bytes], bytes, str]
19
+ FileTypes = Union[
20
+ # (filename, file (or bytes), content_type)
21
+ tuple[Optional[str], FileContent, Optional[str]],
22
+ # (filename, file (or bytes), content_type, headers)
23
+ tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]],
24
+ ]
25
+ RequestFiles = list[tuple[str, FileTypes]]
26
+
27
+
28
+ @define
29
+ class File:
30
+ """Contains information for file uploads"""
31
+
32
+ payload: BinaryIO
33
+ file_name: Optional[str] = None
34
+ mime_type: Optional[str] = None
35
+
36
+ def to_tuple(self) -> FileTypes:
37
+ """Return a tuple representation that httpx will accept for multipart/form-data"""
38
+ return self.file_name, self.payload, self.mime_type
39
+
40
+
41
+ T = TypeVar("T")
42
+
43
+
44
+ @define
45
+ class Response(Generic[T]):
46
+ """A response from an endpoint"""
47
+
48
+ status_code: HTTPStatus
49
+ content: bytes
50
+ headers: MutableMapping[str, str]
51
+ parsed: Optional[T]
52
+
53
+
54
+ __all__ = ["UNSET", "File", "FileTypes", "RequestFiles", "Response", "Unset"]
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.4
2
+ Name: bytekit-sdk
3
+ Version: 0.3.0
4
+ Summary: Official Python SDK for the ByteKit API
5
+ Project-URL: Homepage, https://bytekit.com
6
+ Project-URL: Repository, https://github.com/Hunt-Labs-Inc/ByteKit
7
+ Project-URL: Documentation, https://bytekit.com/docs
8
+ License-Expression: MIT
9
+ Keywords: api,bytekit,crawler,llm,markdown,scraping,screenshots,sdk,web-scraping
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Internet :: WWW/HTTP
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: attrs>=23.1.0
22
+ Requires-Dist: httpx>=0.24.0
23
+ Requires-Dist: python-dateutil>=2.8.0
24
+ Description-Content-Type: text/markdown
25
+
26
+ # bytekit-sdk
27
+
28
+ Official Python SDK for the [ByteKit API](https://bytekit.com).
29
+
30
+ The PyPI **distribution** is `bytekit-sdk`; the **import** name is `bytekit`.
31
+
32
+ Generated from the OpenAPI spec using [openapi-python-client](https://github.com/openapi-generators/openapi-python-client), filtered to the stable v0.1 operations.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install bytekit-sdk
38
+ ```
39
+
40
+ ## Quick start
41
+
42
+ ```python
43
+ from bytekit import AuthenticatedClient
44
+ from bytekit.api.scrape import create_scrape
45
+ from bytekit.errors import UnexpectedStatus
46
+ from bytekit.models.scrape_request import ScrapeRequest
47
+
48
+ # base_url defaults to https://api.bytekit.com, so only the token is required.
49
+ client = AuthenticatedClient(token="sk_live_your_api_key_here")
50
+
51
+ body = ScrapeRequest(url="https://example.com")
52
+
53
+ try:
54
+ response = create_scrape.sync(client=client, body=body)
55
+ # response.formats.markdown is str | Unset — only present when "markdown" was requested
56
+ print(response.formats.markdown)
57
+ except UnexpectedStatus as err:
58
+ # Errors now raise loudly by default instead of returning None.
59
+ print(f"request failed with status {err.status_code}: {err.code} {err.message}")
60
+ ```
61
+
62
+ ### Defaults
63
+
64
+ The client ships with production-ready defaults so `AuthenticatedClient(token=...)` works out of the box:
65
+
66
+ | Setting | Default | Notes |
67
+ | ---------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
68
+ | `base_url` | `https://api.bytekit.com` | Pass `base_url=` to target staging or a proxy. |
69
+ | `timeout` | `120s` (`httpx.Timeout(120.0)`) | Finite by default — requests no longer hang indefinitely. Pass `timeout=` to override. |
70
+ | `raise_on_unexpected_status` | `True` | Undocumented statuses raise `errors.UnexpectedStatus` instead of silently returning `None`. Pass `raise_on_unexpected_status=False` to restore the old opt-out. |
71
+
72
+ Explicit constructor arguments always win over these defaults (explicit arg > default).
73
+
74
+ ## Async usage
75
+
76
+ ```python
77
+ import asyncio
78
+ from bytekit import AuthenticatedClient
79
+ from bytekit.api.screenshots import create_screenshot
80
+ from bytekit.models.screenshot_request import ScreenshotRequest
81
+
82
+ async def main():
83
+ client = AuthenticatedClient(token="sk_live_your_api_key_here")
84
+ body = ScreenshotRequest(url="https://example.com")
85
+ response = await create_screenshot.asyncio(client=client, body=body)
86
+ print(response)
87
+
88
+ asyncio.run(main())
89
+ ```
90
+
91
+ ## Available operations
92
+
93
+ | Module | Method | Description |
94
+ | ----------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
95
+ | `api.scrape` | `create_scrape`, `get_scrape` | Web content extraction |
96
+ | `api.screenshots` | `create_screenshot`, `get_screenshot` | Page screenshots |
97
+ | `api.bulk` | `create_bulk`, `get_bulk`, `delete_bulk`, `list_bulk_screenshots` | Bulk screenshot jobs |
98
+ | `api.scrape_bulk` | `create_scrape_bulk`, `get_scrape_bulk` | Bulk scrape jobs |
99
+ | `api.fetch` | `get_fetch`, `post_fetch` | Raw HTTP fetch |
100
+ | `api.fetch_bulk` | `create_fetch_bulk`, `get_fetch_bulk` | Bulk fetch jobs |
101
+ | `api.monitors` | `create_monitor`, `list_monitors`, `get_monitor`, `update_monitor`, `delete_monitor`, `list_monitor_captures` | Page-change monitors (screenshot + scrape) |
102
+ | `api.sitemap` | `create_sitemap`, `get_sitemap` | Sitemap crawl |
103
+ | `api.search` | `create_search` (or the `AuthenticatedClient.search(...)` convenience method) | Web search |
104
+ | `api.usage` | `get_usage`, `get_usage_daily`, `get_usage_by_endpoint` | Account usage & billing |
105
+ | `api.webhooks` | `list_webhook_deliveries`, `retry_webhook_delivery` | Webhook delivery log & retry |
106
+ | `api.account` | `get_account` | Account details |
107
+
108
+ ## Regenerating
109
+
110
+ To regenerate the client after API changes:
111
+
112
+ ```bash
113
+ pnpm --filter @bytekit/sdk-python generate
114
+ ```
115
+
116
+ This runs `scripts/filter-spec.ts` to produce `filtered-openapi.yaml` (filtered to v0.1 operations), runs `scripts/prune-stale-api.py` to delete any `src/bytekit/api/<tag>/` directory the filtered spec no longer produces (`generate --overwrite` itself already rebuilds `api/` from scratch on every run, so this step is defense-in-depth for a standalone run of the prune script or a future generator version — the path that actually needs the guard is `pnpm generate:docs`, which enumerates `api/` on disk independent of `generate` and can otherwise resurrect a tag whose tracked files were `git rm`-ed but whose untracked `__pycache__/` survives; see `scripts/prune-stale-api.py`'s module docstring and `has_operations()` in `scripts/generate-docs.py`), invokes `openapi-python-client generate` to update `src/bytekit/`, then runs `scripts/inject-handwritten.py` to re-append hand-written fragments (e.g. the `AuthenticatedClient.search()` convenience method) from `scripts/hand_written/` and re-patch the generated `client.py`/`errors.py` with the runtime defaults and error enrichment described above — because `--overwrite` overwrites every file it emits, both the hand-written code and these patches are wiped on every regen and must be re-applied afterward.
117
+
118
+ ## Development
119
+
120
+ ```bash
121
+ # Run tests
122
+ cd packages/sdk-python
123
+ python3 -m pytest tests/ -v
124
+ ```
125
+
126
+ ## Publishing
127
+
128
+ PyPI publish is handled in [#2226](https://github.com/Hunt-Labs-Inc/ByteKit/issues/2226) —
129
+ `.woodpecker/publish.yaml`'s `publish-pypi` step, version-gated the same way as the npm
130
+ siblings (publishes only when the local `pyproject.toml` version differs from what's live on
131
+ PyPI).
132
+
133
+ **`bytekit-sdk` has never been published.** Before the commit that arms
134
+ `packages/sdk-python/pyproject.toml` in `publish.yaml`'s workflow-level `when.path.include` is
135
+ promoted from `staging` to `main`, an operator MUST publish `0.3.0` to PyPI manually and under
136
+ supervision. Reason: bytekit-sdk 404s on PyPI today, so the automatic version-compare gate's
137
+ `|| echo "0.0.0"` fallback always fires — the first time that arming reaches `main`, it would
138
+ trigger a real, irreversible first `twine upload` with no manual confirmation step in between.
139
+ Once the manual first release exists, PUBLISHED == CURRENT and every later automatic run at an
140
+ unchanged version is a no-op, same as the npm packages. See the comment at the armed
141
+ `when.path.include` entry in `.woodpecker/publish.yaml` for the mechanism.