aiondtech 2.1.0__py3-none-any.whl → 2.2.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.
- aiondtech/__init__.py +1 -1
- aiondtech/client.py +7 -613
- aiondtech/models.py +19 -446
- {aiondtech-2.1.0.dist-info → aiondtech-2.2.0.dist-info}/METADATA +34 -15
- aiondtech-2.2.0.dist-info/RECORD +9 -0
- aiondtech-2.1.0.dist-info/RECORD +0 -9
- {aiondtech-2.1.0.dist-info → aiondtech-2.2.0.dist-info}/WHEEL +0 -0
- {aiondtech-2.1.0.dist-info → aiondtech-2.2.0.dist-info}/licenses/LICENSE +0 -0
- {aiondtech-2.1.0.dist-info → aiondtech-2.2.0.dist-info}/top_level.txt +0 -0
aiondtech/__init__.py
CHANGED
aiondtech/client.py
CHANGED
|
@@ -1,609 +1,3 @@
|
|
|
1
|
-
# """
|
|
2
|
-
# AiondTech Resume Analyser API Client - Updated Version
|
|
3
|
-
|
|
4
|
-
# This is the main entry point for interacting with the API.
|
|
5
|
-
# Supports all external endpoints with credit tracking.
|
|
6
|
-
|
|
7
|
-
# Endpoints:
|
|
8
|
-
# - resumes.upload() - Upload resume, get ID
|
|
9
|
-
# - resumes.upload_and_analyze() - Upload + parse
|
|
10
|
-
# - resumes.upload_analyze_compare() - Upload + parse + compare to job
|
|
11
|
-
# - resumes.analyze() - Parse existing resume by ID
|
|
12
|
-
# - resumes.list() - List all uploaded resumes
|
|
13
|
-
# - jobs.create() - Create job posting
|
|
14
|
-
# - jobs.list() - List all jobs
|
|
15
|
-
# - matching.compare() - Compare resume to job
|
|
16
|
-
# """
|
|
17
|
-
|
|
18
|
-
# import os
|
|
19
|
-
# import mimetypes
|
|
20
|
-
# from typing import Optional, Dict, Any, List, Union
|
|
21
|
-
# from urllib.parse import urljoin
|
|
22
|
-
|
|
23
|
-
# import requests
|
|
24
|
-
|
|
25
|
-
# from .models import (
|
|
26
|
-
# ResumeUploadResult,
|
|
27
|
-
# ResumeAnalysisResult,
|
|
28
|
-
# ResumeComparisonResult,
|
|
29
|
-
# JobResult,
|
|
30
|
-
# ResumeListResult,
|
|
31
|
-
# JobListResult,
|
|
32
|
-
# ParsedResumeResult,
|
|
33
|
-
# APIError,
|
|
34
|
-
# AuthenticationError,
|
|
35
|
-
# RateLimitError,
|
|
36
|
-
# ValidationError,
|
|
37
|
-
# NotFoundError,
|
|
38
|
-
# InsufficientCreditsError,
|
|
39
|
-
# )
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
# # Default API base URLs
|
|
43
|
-
# DEFAULT_BASE_URL = "https://api.dev.aiondtech.com"
|
|
44
|
-
# PRODUCTION_BASE_URL = "https://api.aiondtech.com"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
# class HTTPClient:
|
|
48
|
-
# """Low-level HTTP client for API requests."""
|
|
49
|
-
|
|
50
|
-
# def __init__(
|
|
51
|
-
# self,
|
|
52
|
-
# api_key: str,
|
|
53
|
-
# base_url: str,
|
|
54
|
-
# timeout: int = 120,
|
|
55
|
-
# max_retries: int = 3
|
|
56
|
-
# ):
|
|
57
|
-
# self.api_key = api_key
|
|
58
|
-
# self.base_url = base_url.rstrip("/")
|
|
59
|
-
# self.timeout = timeout
|
|
60
|
-
# self.max_retries = max_retries
|
|
61
|
-
|
|
62
|
-
# self.session = requests.Session()
|
|
63
|
-
# self.session.headers.update({
|
|
64
|
-
# "Accept": "application/json",
|
|
65
|
-
# "User-Agent": "aiondtech-python/2.0.0",
|
|
66
|
-
# "X-API-Key": api_key,
|
|
67
|
-
# })
|
|
68
|
-
|
|
69
|
-
# def request(
|
|
70
|
-
# self,
|
|
71
|
-
# method: str,
|
|
72
|
-
# endpoint: str,
|
|
73
|
-
# data: Optional[Dict] = None,
|
|
74
|
-
# json_data: Optional[Dict] = None,
|
|
75
|
-
# files: Optional[Dict] = None,
|
|
76
|
-
# params: Optional[Dict] = None,
|
|
77
|
-
# ) -> Any:
|
|
78
|
-
# """Make an HTTP request to the API."""
|
|
79
|
-
# url = f"{self.base_url}{endpoint}"
|
|
80
|
-
|
|
81
|
-
# try:
|
|
82
|
-
# response = self.session.request(
|
|
83
|
-
# method=method,
|
|
84
|
-
# url=url,
|
|
85
|
-
# data=data,
|
|
86
|
-
# json=json_data,
|
|
87
|
-
# files=files,
|
|
88
|
-
# params=params,
|
|
89
|
-
# timeout=self.timeout,
|
|
90
|
-
# )
|
|
91
|
-
|
|
92
|
-
# return self._handle_response(response)
|
|
93
|
-
|
|
94
|
-
# except requests.exceptions.Timeout:
|
|
95
|
-
# raise APIError("Request timed out", status_code=408)
|
|
96
|
-
# except requests.exceptions.ConnectionError:
|
|
97
|
-
# raise APIError("Failed to connect to API server")
|
|
98
|
-
# except requests.exceptions.RequestException as e:
|
|
99
|
-
# raise APIError(f"Request failed: {str(e)}")
|
|
100
|
-
|
|
101
|
-
# def _handle_response(self, response: requests.Response) -> Any:
|
|
102
|
-
# """Handle API response and raise appropriate exceptions."""
|
|
103
|
-
|
|
104
|
-
# # Try to parse JSON response
|
|
105
|
-
# try:
|
|
106
|
-
# data = response.json()
|
|
107
|
-
# except ValueError:
|
|
108
|
-
# data = {"detail": response.text}
|
|
109
|
-
|
|
110
|
-
# # Handle error responses
|
|
111
|
-
# if response.status_code == 401:
|
|
112
|
-
# raise AuthenticationError(
|
|
113
|
-
# data.get("detail", "Invalid API key"),
|
|
114
|
-
# status_code=401,
|
|
115
|
-
# response=data
|
|
116
|
-
# )
|
|
117
|
-
|
|
118
|
-
# if response.status_code == 403:
|
|
119
|
-
# detail = data.get("detail", "")
|
|
120
|
-
# if "credit" in detail.lower():
|
|
121
|
-
# raise InsufficientCreditsError(
|
|
122
|
-
# detail or "Insufficient API credits",
|
|
123
|
-
# status_code=403,
|
|
124
|
-
# response=data
|
|
125
|
-
# )
|
|
126
|
-
# raise AuthenticationError(
|
|
127
|
-
# detail or "Invalid or inactive API key",
|
|
128
|
-
# status_code=403,
|
|
129
|
-
# response=data
|
|
130
|
-
# )
|
|
131
|
-
|
|
132
|
-
# if response.status_code == 404:
|
|
133
|
-
# raise NotFoundError(
|
|
134
|
-
# data.get("detail", "Resource not found"),
|
|
135
|
-
# status_code=404,
|
|
136
|
-
# response=data
|
|
137
|
-
# )
|
|
138
|
-
|
|
139
|
-
# if response.status_code == 422:
|
|
140
|
-
# raise ValidationError(
|
|
141
|
-
# data.get("detail", "Validation error"),
|
|
142
|
-
# status_code=422,
|
|
143
|
-
# response=data
|
|
144
|
-
# )
|
|
145
|
-
|
|
146
|
-
# if response.status_code == 429:
|
|
147
|
-
# retry_after = response.headers.get("Retry-After")
|
|
148
|
-
# raise RateLimitError(
|
|
149
|
-
# data.get("detail", "Rate limit exceeded"),
|
|
150
|
-
# retry_after=int(retry_after) if retry_after else None,
|
|
151
|
-
# status_code=429,
|
|
152
|
-
# response=data
|
|
153
|
-
# )
|
|
154
|
-
|
|
155
|
-
# if response.status_code >= 500:
|
|
156
|
-
# raise APIError(
|
|
157
|
-
# data.get("detail", "Server error"),
|
|
158
|
-
# status_code=response.status_code,
|
|
159
|
-
# response=data
|
|
160
|
-
# )
|
|
161
|
-
|
|
162
|
-
# if response.status_code >= 400:
|
|
163
|
-
# raise APIError(
|
|
164
|
-
# data.get("detail", f"Request failed with status {response.status_code}"),
|
|
165
|
-
# status_code=response.status_code,
|
|
166
|
-
# response=data
|
|
167
|
-
# )
|
|
168
|
-
|
|
169
|
-
# return data
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
# class Resumes:
|
|
173
|
-
# """
|
|
174
|
-
# Resume operations.
|
|
175
|
-
|
|
176
|
-
# Usage:
|
|
177
|
-
# client.resumes.upload("resume.pdf")
|
|
178
|
-
# client.resumes.upload_and_analyze("resume.pdf")
|
|
179
|
-
# client.resumes.upload_analyze_compare("resume.pdf", job_id=123)
|
|
180
|
-
# client.resumes.analyze(resume_id=123)
|
|
181
|
-
# client.resumes.list()
|
|
182
|
-
# """
|
|
183
|
-
|
|
184
|
-
# def __init__(self, client: HTTPClient):
|
|
185
|
-
# self._client = client
|
|
186
|
-
|
|
187
|
-
# def upload(self, file_path: str) -> ResumeUploadResult:
|
|
188
|
-
# """
|
|
189
|
-
# Upload a resume file (PDF only).
|
|
190
|
-
|
|
191
|
-
# Credits: 1 API credit
|
|
192
|
-
|
|
193
|
-
# Args:
|
|
194
|
-
# file_path: Path to the resume file (PDF)
|
|
195
|
-
|
|
196
|
-
# Returns:
|
|
197
|
-
# ResumeUploadResult with resume_id
|
|
198
|
-
|
|
199
|
-
# Example:
|
|
200
|
-
# result = client.resumes.upload("path/to/resume.pdf")
|
|
201
|
-
# print(f"Uploaded resume ID: {result.resume_id}")
|
|
202
|
-
# """
|
|
203
|
-
# self._validate_file(file_path)
|
|
204
|
-
|
|
205
|
-
# mime_type = mimetypes.guess_type(file_path)[0] or "application/pdf"
|
|
206
|
-
# filename = os.path.basename(file_path)
|
|
207
|
-
|
|
208
|
-
# with open(file_path, "rb") as f:
|
|
209
|
-
# files = {"file": (filename, f, mime_type)}
|
|
210
|
-
# data = self._client.request("POST", "/external/upload-resume", files=files)
|
|
211
|
-
|
|
212
|
-
# return ResumeUploadResult.from_response(data)
|
|
213
|
-
|
|
214
|
-
# def upload_and_analyze(self, file_path: str) -> ResumeAnalysisResult:
|
|
215
|
-
# """
|
|
216
|
-
# Upload a resume and parse/extract structured data.
|
|
217
|
-
|
|
218
|
-
# Credits: 3 API credits (includes AI parsing)
|
|
219
|
-
|
|
220
|
-
# Args:
|
|
221
|
-
# file_path: Path to the resume file (PDF)
|
|
222
|
-
|
|
223
|
-
# Returns:
|
|
224
|
-
# ResumeAnalysisResult with resume_id and parsed_data
|
|
225
|
-
|
|
226
|
-
# Example:
|
|
227
|
-
# result = client.resumes.upload_and_analyze("resume.pdf")
|
|
228
|
-
# print(f"Name: {result.parsed_data.get('full_name')}")
|
|
229
|
-
# print(f"Skills: {result.parsed_data.get('skills')}")
|
|
230
|
-
# """
|
|
231
|
-
# self._validate_file(file_path)
|
|
232
|
-
|
|
233
|
-
# mime_type = mimetypes.guess_type(file_path)[0] or "application/pdf"
|
|
234
|
-
# filename = os.path.basename(file_path)
|
|
235
|
-
|
|
236
|
-
# with open(file_path, "rb") as f:
|
|
237
|
-
# files = {"file": (filename, f, mime_type)}
|
|
238
|
-
# data = self._client.request(
|
|
239
|
-
# "POST",
|
|
240
|
-
# "/external/upload-resume-analyze",
|
|
241
|
-
# files=files
|
|
242
|
-
# )
|
|
243
|
-
|
|
244
|
-
# return ResumeAnalysisResult.from_response(data)
|
|
245
|
-
|
|
246
|
-
# def upload_analyze_compare(
|
|
247
|
-
# self,
|
|
248
|
-
# file_path: str,
|
|
249
|
-
# job_id: int
|
|
250
|
-
# ) -> ResumeComparisonResult:
|
|
251
|
-
# """
|
|
252
|
-
# Upload, parse, and compare resume against a job posting.
|
|
253
|
-
|
|
254
|
-
# Credits: 5 API credits (includes AI parsing + comparison)
|
|
255
|
-
|
|
256
|
-
# Args:
|
|
257
|
-
# file_path: Path to the resume file (PDF)
|
|
258
|
-
# job_id: ID of the job posting to compare against
|
|
259
|
-
|
|
260
|
-
# Returns:
|
|
261
|
-
# ResumeComparisonResult with resume_id, parsed_data, score, and reason
|
|
262
|
-
|
|
263
|
-
# Example:
|
|
264
|
-
# result = client.resumes.upload_analyze_compare("resume.pdf", job_id=42)
|
|
265
|
-
# print(f"Match Score: {result.comparison_score}%")
|
|
266
|
-
# print(f"Reason: {result.comparison_reason}")
|
|
267
|
-
# """
|
|
268
|
-
# self._validate_file(file_path)
|
|
269
|
-
|
|
270
|
-
# mime_type = mimetypes.guess_type(file_path)[0] or "application/pdf"
|
|
271
|
-
# filename = os.path.basename(file_path)
|
|
272
|
-
|
|
273
|
-
# with open(file_path, "rb") as f:
|
|
274
|
-
# files = {"file": (filename, f, mime_type)}
|
|
275
|
-
# form_data = {"job_id": str(job_id)}
|
|
276
|
-
# data = self._client.request(
|
|
277
|
-
# "POST",
|
|
278
|
-
# "/external/upload-resume-analyze-compare",
|
|
279
|
-
# files=files,
|
|
280
|
-
# data=form_data
|
|
281
|
-
# )
|
|
282
|
-
|
|
283
|
-
# return ResumeComparisonResult.from_response(data)
|
|
284
|
-
|
|
285
|
-
# def analyze(self, resume_id: int) -> ParsedResumeResult:
|
|
286
|
-
# """
|
|
287
|
-
# Parse and extract structured data from an existing resume.
|
|
288
|
-
|
|
289
|
-
# Credits: 2 API credits (AI parsing only)
|
|
290
|
-
|
|
291
|
-
# Args:
|
|
292
|
-
# resume_id: ID of the uploaded resume
|
|
293
|
-
|
|
294
|
-
# Returns:
|
|
295
|
-
# ParsedResumeResult with extracted fields
|
|
296
|
-
|
|
297
|
-
# Example:
|
|
298
|
-
# parsed = client.resumes.analyze(resume_id=123)
|
|
299
|
-
# print(f"Name: {parsed.full_name}")
|
|
300
|
-
# print(f"Skills: {parsed.skills}")
|
|
301
|
-
# """
|
|
302
|
-
# data = self._client.request(
|
|
303
|
-
# "POST",
|
|
304
|
-
# "/external/analyze-resume-by-id",
|
|
305
|
-
# params={"resume_id": resume_id}
|
|
306
|
-
# )
|
|
307
|
-
# return ParsedResumeResult.from_response(data)
|
|
308
|
-
|
|
309
|
-
# def list(
|
|
310
|
-
# self,
|
|
311
|
-
# page: int = 1,
|
|
312
|
-
# limit: int = 50
|
|
313
|
-
# ) -> ResumeListResult:
|
|
314
|
-
# """
|
|
315
|
-
# List all uploaded resumes for this API key.
|
|
316
|
-
|
|
317
|
-
# Credits: 0 (free)
|
|
318
|
-
|
|
319
|
-
# Args:
|
|
320
|
-
# page: Page number (default: 1)
|
|
321
|
-
# limit: Items per page (default: 50, max: 100)
|
|
322
|
-
|
|
323
|
-
# Returns:
|
|
324
|
-
# ResumeListResult with list of resumes and pagination
|
|
325
|
-
|
|
326
|
-
# Example:
|
|
327
|
-
# result = client.resumes.list()
|
|
328
|
-
# for resume in result.resumes:
|
|
329
|
-
# print(f"ID: {resume['id']}, Name: {resume.get('full_name')}")
|
|
330
|
-
# """
|
|
331
|
-
# data = self._client.request(
|
|
332
|
-
# "GET",
|
|
333
|
-
# "/external/list-resumes",
|
|
334
|
-
# params={"page": page, "limit": min(limit, 100)}
|
|
335
|
-
# )
|
|
336
|
-
# return ResumeListResult.from_response(data)
|
|
337
|
-
|
|
338
|
-
# def _validate_file(self, file_path: str) -> None:
|
|
339
|
-
# """Validate file exists and is PDF."""
|
|
340
|
-
# if not os.path.exists(file_path):
|
|
341
|
-
# raise ValidationError(f"File not found: {file_path}")
|
|
342
|
-
|
|
343
|
-
# ext = os.path.splitext(file_path)[1].lower()
|
|
344
|
-
# if ext != ".pdf":
|
|
345
|
-
# raise ValidationError(
|
|
346
|
-
# f"Invalid file type: {ext}. Only PDF files are supported."
|
|
347
|
-
# )
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
# class Jobs:
|
|
351
|
-
# """
|
|
352
|
-
# Job posting operations.
|
|
353
|
-
|
|
354
|
-
# Usage:
|
|
355
|
-
# client.jobs.create("Python Developer", "Job description...")
|
|
356
|
-
# client.jobs.list()
|
|
357
|
-
# """
|
|
358
|
-
|
|
359
|
-
# def __init__(self, client: HTTPClient):
|
|
360
|
-
# self._client = client
|
|
361
|
-
|
|
362
|
-
# def create(self, title: str, description: str) -> JobResult:
|
|
363
|
-
# """
|
|
364
|
-
# Create a new job posting.
|
|
365
|
-
|
|
366
|
-
# Credits: 1 API credit
|
|
367
|
-
|
|
368
|
-
# Args:
|
|
369
|
-
# title: Job title
|
|
370
|
-
# description: Full job description
|
|
371
|
-
|
|
372
|
-
# Returns:
|
|
373
|
-
# JobResult with job_id
|
|
374
|
-
|
|
375
|
-
# Example:
|
|
376
|
-
# job = client.jobs.create(
|
|
377
|
-
# title="Senior Python Developer",
|
|
378
|
-
# description="We are looking for..."
|
|
379
|
-
# )
|
|
380
|
-
# print(f"Created job ID: {job.job_id}")
|
|
381
|
-
# """
|
|
382
|
-
# form_data = {
|
|
383
|
-
# "title": title,
|
|
384
|
-
# "description": description
|
|
385
|
-
# }
|
|
386
|
-
# data = self._client.request("POST", "/external/create-job", data=form_data)
|
|
387
|
-
# return JobResult.from_response(data)
|
|
388
|
-
|
|
389
|
-
# def list(
|
|
390
|
-
# self,
|
|
391
|
-
# page: int = 1,
|
|
392
|
-
# limit: int = 50
|
|
393
|
-
# ) -> JobListResult:
|
|
394
|
-
# """
|
|
395
|
-
# List all job postings for this API key.
|
|
396
|
-
|
|
397
|
-
# Credits: 0 (free)
|
|
398
|
-
|
|
399
|
-
# Args:
|
|
400
|
-
# page: Page number (default: 1)
|
|
401
|
-
# limit: Items per page (default: 50, max: 100)
|
|
402
|
-
|
|
403
|
-
# Returns:
|
|
404
|
-
# JobListResult with list of jobs and pagination
|
|
405
|
-
|
|
406
|
-
# Example:
|
|
407
|
-
# result = client.jobs.list()
|
|
408
|
-
# for job in result.jobs:
|
|
409
|
-
# print(f"ID: {job['id']}, Title: {job['title']}")
|
|
410
|
-
# """
|
|
411
|
-
# data = self._client.request(
|
|
412
|
-
# "GET",
|
|
413
|
-
# "/external/list-jobs",
|
|
414
|
-
# params={"page": page, "limit": min(limit, 100)}
|
|
415
|
-
# )
|
|
416
|
-
# return JobListResult.from_response(data)
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
# class Matching:
|
|
420
|
-
# """
|
|
421
|
-
# Resume-job matching/comparison operations.
|
|
422
|
-
|
|
423
|
-
# Usage:
|
|
424
|
-
# client.matching.compare(resume_id=123, job_id=456)
|
|
425
|
-
# """
|
|
426
|
-
|
|
427
|
-
# def __init__(self, client: HTTPClient):
|
|
428
|
-
# self._client = client
|
|
429
|
-
|
|
430
|
-
# def compare(
|
|
431
|
-
# self,
|
|
432
|
-
# resume_id: int,
|
|
433
|
-
# job_id: int
|
|
434
|
-
# ) -> ResumeComparisonResult:
|
|
435
|
-
# """
|
|
436
|
-
# Compare a resume against a job posting.
|
|
437
|
-
|
|
438
|
-
# Credits: 3 API credits (AI comparison)
|
|
439
|
-
|
|
440
|
-
# Args:
|
|
441
|
-
# resume_id: ID of the uploaded resume
|
|
442
|
-
# job_id: ID of the job posting
|
|
443
|
-
|
|
444
|
-
# Returns:
|
|
445
|
-
# ResumeComparisonResult with score and reasoning
|
|
446
|
-
|
|
447
|
-
# Example:
|
|
448
|
-
# result = client.matching.compare(resume_id=123, job_id=456)
|
|
449
|
-
# print(f"Match Score: {result.comparison_score}%")
|
|
450
|
-
# print(f"Reasoning: {result.comparison_reason}")
|
|
451
|
-
# """
|
|
452
|
-
# payload = {
|
|
453
|
-
# "resume_id": resume_id,
|
|
454
|
-
# "job_id": job_id
|
|
455
|
-
# }
|
|
456
|
-
# data = self._client.request(
|
|
457
|
-
# "POST",
|
|
458
|
-
# "/external/compare-resumes",
|
|
459
|
-
# json_data=payload
|
|
460
|
-
# )
|
|
461
|
-
# return ResumeComparisonResult.from_response(data)
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
# class Credits:
|
|
465
|
-
# """
|
|
466
|
-
# Credit balance and usage operations.
|
|
467
|
-
|
|
468
|
-
# Usage:
|
|
469
|
-
# client.credits.balance()
|
|
470
|
-
# client.credits.usage()
|
|
471
|
-
# """
|
|
472
|
-
|
|
473
|
-
# def __init__(self, client: HTTPClient):
|
|
474
|
-
# self._client = client
|
|
475
|
-
|
|
476
|
-
# def balance(self) -> Dict[str, Any]:
|
|
477
|
-
# """
|
|
478
|
-
# Get current credit balance.
|
|
479
|
-
|
|
480
|
-
# Returns:
|
|
481
|
-
# Dictionary with credit balance info
|
|
482
|
-
|
|
483
|
-
# Example:
|
|
484
|
-
# balance = client.credits.balance()
|
|
485
|
-
# print(f"Remaining: {balance['remaining']}")
|
|
486
|
-
# print(f"Used this month: {balance['used_mtd']}")
|
|
487
|
-
# """
|
|
488
|
-
# data = self._client.request("GET", "/external/credits/balance")
|
|
489
|
-
# return data
|
|
490
|
-
|
|
491
|
-
# def usage(
|
|
492
|
-
# self,
|
|
493
|
-
# start_date: Optional[str] = None,
|
|
494
|
-
# end_date: Optional[str] = None
|
|
495
|
-
# ) -> Dict[str, Any]:
|
|
496
|
-
# """
|
|
497
|
-
# Get detailed usage history.
|
|
498
|
-
|
|
499
|
-
# Args:
|
|
500
|
-
# start_date: Start date (YYYY-MM-DD)
|
|
501
|
-
# end_date: End date (YYYY-MM-DD)
|
|
502
|
-
|
|
503
|
-
# Returns:
|
|
504
|
-
# Dictionary with usage details
|
|
505
|
-
|
|
506
|
-
# Example:
|
|
507
|
-
# usage = client.credits.usage()
|
|
508
|
-
# for entry in usage['history']:
|
|
509
|
-
# print(f"{entry['endpoint']}: {entry['credits']} credits")
|
|
510
|
-
# """
|
|
511
|
-
# params = {}
|
|
512
|
-
# if start_date:
|
|
513
|
-
# params["start_date"] = start_date
|
|
514
|
-
# if end_date:
|
|
515
|
-
# params["end_date"] = end_date
|
|
516
|
-
|
|
517
|
-
# data = self._client.request("GET", "/external/credits/usage", params=params)
|
|
518
|
-
# return data
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
# class ResumeAnalyser:
|
|
522
|
-
# """
|
|
523
|
-
# AiondTech Resume Analyser API Client.
|
|
524
|
-
|
|
525
|
-
# This is the main entry point for interacting with the API.
|
|
526
|
-
|
|
527
|
-
# Args:
|
|
528
|
-
# api_key: Your API key. Can also be set via AIONDTECH_API_KEY env var.
|
|
529
|
-
# base_url: API base URL. Defaults to https://api.dev.aiondtech.com
|
|
530
|
-
# timeout: Request timeout in seconds. Default 120.
|
|
531
|
-
# production: If True, use production URL (https://api.aiondtech.com)
|
|
532
|
-
|
|
533
|
-
# Example:
|
|
534
|
-
# from aiondtech import ResumeAnalyser
|
|
535
|
-
|
|
536
|
-
# # Initialize client
|
|
537
|
-
# client = ResumeAnalyser(api_key="your-api-key")
|
|
538
|
-
|
|
539
|
-
# # Or use environment variable
|
|
540
|
-
# # export AIONDTECH_API_KEY="your-api-key"
|
|
541
|
-
# client = ResumeAnalyser()
|
|
542
|
-
|
|
543
|
-
# # Upload resume
|
|
544
|
-
# result = client.resumes.upload("resume.pdf")
|
|
545
|
-
|
|
546
|
-
# # Upload and analyze
|
|
547
|
-
# analysis = client.resumes.upload_and_analyze("resume.pdf")
|
|
548
|
-
|
|
549
|
-
# # Create job posting
|
|
550
|
-
# job = client.jobs.create("Title", "Description")
|
|
551
|
-
|
|
552
|
-
# # Compare resume to job
|
|
553
|
-
# comparison = client.matching.compare(
|
|
554
|
-
# resume_id=result.resume_id,
|
|
555
|
-
# job_id=job.job_id
|
|
556
|
-
# )
|
|
557
|
-
|
|
558
|
-
# # Check credits
|
|
559
|
-
# balance = client.credits.balance()
|
|
560
|
-
# """
|
|
561
|
-
|
|
562
|
-
# def __init__(
|
|
563
|
-
# self,
|
|
564
|
-
# api_key: Optional[str] = None,
|
|
565
|
-
# base_url: Optional[str] = None,
|
|
566
|
-
# timeout: int = 120,
|
|
567
|
-
# production: bool = False,
|
|
568
|
-
# ):
|
|
569
|
-
# # Get API key from argument or environment
|
|
570
|
-
# self.api_key = api_key or os.getenv("AIONDTECH_API_KEY")
|
|
571
|
-
# if not self.api_key:
|
|
572
|
-
# raise AuthenticationError(
|
|
573
|
-
# "API key is required. Pass api_key argument or set AIONDTECH_API_KEY environment variable."
|
|
574
|
-
# )
|
|
575
|
-
|
|
576
|
-
# # Get base URL
|
|
577
|
-
# if base_url:
|
|
578
|
-
# self.base_url = base_url
|
|
579
|
-
# elif production:
|
|
580
|
-
# self.base_url = PRODUCTION_BASE_URL
|
|
581
|
-
# else:
|
|
582
|
-
# self.base_url = os.getenv("AIONDTECH_BASE_URL") or DEFAULT_BASE_URL
|
|
583
|
-
|
|
584
|
-
# # Initialize HTTP client
|
|
585
|
-
# self._client = HTTPClient(
|
|
586
|
-
# api_key=self.api_key,
|
|
587
|
-
# base_url=self.base_url,
|
|
588
|
-
# timeout=timeout,
|
|
589
|
-
# )
|
|
590
|
-
|
|
591
|
-
# # Initialize resource classes
|
|
592
|
-
# self.resumes = Resumes(self._client)
|
|
593
|
-
# self.jobs = Jobs(self._client)
|
|
594
|
-
# self.matching = Matching(self._client)
|
|
595
|
-
# self.credits = Credits(self._client)
|
|
596
|
-
|
|
597
|
-
# def __repr__(self):
|
|
598
|
-
# masked_key = f"{self.api_key[:8]}...{self.api_key[-4:]}" if len(self.api_key) > 12 else "***"
|
|
599
|
-
# return f"<ResumeAnalyser base_url='{self.base_url}' api_key='{masked_key}'>"
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
# # Alias for convenience
|
|
603
|
-
# Client = ResumeAnalyser
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
1
|
"""
|
|
608
2
|
AiondTech Resume Analyser API Client - Updated Version
|
|
609
3
|
|
|
@@ -668,7 +62,7 @@ class HTTPClient:
|
|
|
668
62
|
self.session = requests.Session()
|
|
669
63
|
self.session.headers.update({
|
|
670
64
|
"Accept": "application/json",
|
|
671
|
-
"User-Agent": "aiondtech-python/2.
|
|
65
|
+
"User-Agent": "aiondtech-python/2.2.0",
|
|
672
66
|
"X-API-Key": api_key,
|
|
673
67
|
})
|
|
674
68
|
|
|
@@ -794,7 +188,7 @@ class Resumes:
|
|
|
794
188
|
"""
|
|
795
189
|
Upload a resume file (PDF only).
|
|
796
190
|
|
|
797
|
-
Credits:
|
|
191
|
+
Credits: Varies
|
|
798
192
|
|
|
799
193
|
Args:
|
|
800
194
|
file_path: Path to the resume file (PDF)
|
|
@@ -821,7 +215,7 @@ class Resumes:
|
|
|
821
215
|
"""
|
|
822
216
|
Upload a resume and parse/extract structured data.
|
|
823
217
|
|
|
824
|
-
Credits:
|
|
218
|
+
Credits: Varies (includes AI parsing)
|
|
825
219
|
|
|
826
220
|
Args:
|
|
827
221
|
file_path: Path to the resume file (PDF)
|
|
@@ -857,7 +251,7 @@ class Resumes:
|
|
|
857
251
|
"""
|
|
858
252
|
Upload, parse, and compare resume against a job posting.
|
|
859
253
|
|
|
860
|
-
Credits:
|
|
254
|
+
Credits: Varies (includes AI parsing + comparison)
|
|
861
255
|
|
|
862
256
|
Args:
|
|
863
257
|
file_path: Path to the resume file (PDF)
|
|
@@ -892,7 +286,7 @@ class Resumes:
|
|
|
892
286
|
"""
|
|
893
287
|
Parse and extract structured data from an existing resume.
|
|
894
288
|
|
|
895
|
-
Credits:
|
|
289
|
+
Credits: Varies (AI parsing)
|
|
896
290
|
|
|
897
291
|
Args:
|
|
898
292
|
resume_id: ID of the uploaded resume
|
|
@@ -949,7 +343,7 @@ class Resumes:
|
|
|
949
343
|
"""
|
|
950
344
|
Compare a resume against a job posting.
|
|
951
345
|
|
|
952
|
-
Credits:
|
|
346
|
+
Credits: Varies (AI comparison)
|
|
953
347
|
|
|
954
348
|
Args:
|
|
955
349
|
resume_id: ID of the uploaded resume
|
|
@@ -1003,7 +397,7 @@ class Jobs:
|
|
|
1003
397
|
"""
|
|
1004
398
|
Create a new job posting.
|
|
1005
399
|
|
|
1006
|
-
Credits:
|
|
400
|
+
Credits: Varies
|
|
1007
401
|
|
|
1008
402
|
Args:
|
|
1009
403
|
title: Job title
|