careerlm 1.0.0__tar.gz

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.
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: careerlm
3
+ Version: 1.0.0
4
+ Summary: Official Python SDK for the CareerLM API — world's first career intelligence API
5
+ Home-page: https://careerstudiomax.com/api/docs
6
+ Author: Career Studio
7
+ Author-email: api@careerstudiomax.com
8
+ Project-URL: Documentation, https://careerstudiomax.com/api/docs
9
+ Project-URL: Source, https://github.com/owolat4real/career-studio
10
+ Project-URL: Bug Tracker, https://github.com/owolat4real/career-studio/issues
11
+ Keywords: career,ai,cv,resume,salary,api,careerlm
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: httpx>=0.24.0
20
+ Dynamic: author
21
+ Dynamic: author-email
22
+ Dynamic: classifier
23
+ Dynamic: description
24
+ Dynamic: description-content-type
25
+ Dynamic: home-page
26
+ Dynamic: keywords
27
+ Dynamic: project-url
28
+ Dynamic: requires-dist
29
+ Dynamic: requires-python
30
+ Dynamic: summary
31
+
32
+ # CareerLM Python SDK
33
+
34
+ Official Python client for the [CareerLM API](https://careerstudiomax.com/api/docs) — world's first career intelligence API.
35
+
36
+ ## Install
37
+
38
+ ```bash
39
+ pip install careerlm
40
+ ```
41
+
42
+ ## Quickstart
43
+
44
+ ```python
45
+ from careerlm import CareerLM
46
+
47
+ client = CareerLM(api_key="csk_live_v1_your_key_here")
48
+
49
+ score = client.cv.score(cv_text, job_description)
50
+ print(score["ats_score"]) # 87
51
+ print(score["grade"]) # "B+"
52
+ ```
53
+
54
+ ## What you can do
55
+
56
+ | Method | Description |
57
+ |---|---|
58
+ | `client.cv.score(cv_text, job_description)` | Score a CV against a job description |
59
+ | `client.cv.optimise(cv_text, job_description)` | Rewrite and optimise a CV for a target role |
60
+ | `client.salary.benchmark(role, country)` | Salary benchmarking across 196 countries, PPP-adjusted |
61
+ | `client.cover_letter.generate(cv_text, job_description, mode=1)` | Generate a cover letter in one of 15 professional modes |
62
+ | `client.job.match(candidate, job)` | Score how well a candidate matches a job |
63
+ | `client.interview.questions(role)` | Tailored interview questions with model answers |
64
+ | `client.skills.gap(current_skills, target_role)` | Skill-gap analysis with learning ROI and timeline |
65
+ | `client.chat.completions.create(messages)` | OpenAI-compatible career chat completions |
66
+ | `client.context.save(profile)` / `.get(id)` / `.delete(id)` | Persistent career context across calls |
67
+
68
+ ## Example: salary benchmark
69
+
70
+ ```python
71
+ salary = client.salary.benchmark("Data Engineer", "NG", city="Lagos", currency="NGN")
72
+ print(salary["salary_range"]["median"]) # 6800000
73
+ ```
74
+
75
+ ## Example: cover letter
76
+
77
+ ```python
78
+ letter = client.cover_letter.generate(
79
+ cv_text, job_description,
80
+ mode=5, company_name="Paystack", tone="confident",
81
+ )
82
+ print(letter["content"])
83
+ ```
84
+
85
+ ## Errors
86
+
87
+ ```python
88
+ from careerlm import CareerLM, CareerLMError
89
+
90
+ try:
91
+ client.cv.score(cv_text, job_description)
92
+ except CareerLMError as e:
93
+ print(e.code, e.status, str(e))
94
+ ```
95
+
96
+ ## Context manager
97
+
98
+ ```python
99
+ with CareerLM(api_key="...") as client:
100
+ ...
101
+ ```
102
+
103
+ Full endpoint reference: [careerstudiomax.com/api/docs](https://careerstudiomax.com/api/docs)
@@ -0,0 +1,72 @@
1
+ # CareerLM Python SDK
2
+
3
+ Official Python client for the [CareerLM API](https://careerstudiomax.com/api/docs) — world's first career intelligence API.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install careerlm
9
+ ```
10
+
11
+ ## Quickstart
12
+
13
+ ```python
14
+ from careerlm import CareerLM
15
+
16
+ client = CareerLM(api_key="csk_live_v1_your_key_here")
17
+
18
+ score = client.cv.score(cv_text, job_description)
19
+ print(score["ats_score"]) # 87
20
+ print(score["grade"]) # "B+"
21
+ ```
22
+
23
+ ## What you can do
24
+
25
+ | Method | Description |
26
+ |---|---|
27
+ | `client.cv.score(cv_text, job_description)` | Score a CV against a job description |
28
+ | `client.cv.optimise(cv_text, job_description)` | Rewrite and optimise a CV for a target role |
29
+ | `client.salary.benchmark(role, country)` | Salary benchmarking across 196 countries, PPP-adjusted |
30
+ | `client.cover_letter.generate(cv_text, job_description, mode=1)` | Generate a cover letter in one of 15 professional modes |
31
+ | `client.job.match(candidate, job)` | Score how well a candidate matches a job |
32
+ | `client.interview.questions(role)` | Tailored interview questions with model answers |
33
+ | `client.skills.gap(current_skills, target_role)` | Skill-gap analysis with learning ROI and timeline |
34
+ | `client.chat.completions.create(messages)` | OpenAI-compatible career chat completions |
35
+ | `client.context.save(profile)` / `.get(id)` / `.delete(id)` | Persistent career context across calls |
36
+
37
+ ## Example: salary benchmark
38
+
39
+ ```python
40
+ salary = client.salary.benchmark("Data Engineer", "NG", city="Lagos", currency="NGN")
41
+ print(salary["salary_range"]["median"]) # 6800000
42
+ ```
43
+
44
+ ## Example: cover letter
45
+
46
+ ```python
47
+ letter = client.cover_letter.generate(
48
+ cv_text, job_description,
49
+ mode=5, company_name="Paystack", tone="confident",
50
+ )
51
+ print(letter["content"])
52
+ ```
53
+
54
+ ## Errors
55
+
56
+ ```python
57
+ from careerlm import CareerLM, CareerLMError
58
+
59
+ try:
60
+ client.cv.score(cv_text, job_description)
61
+ except CareerLMError as e:
62
+ print(e.code, e.status, str(e))
63
+ ```
64
+
65
+ ## Context manager
66
+
67
+ ```python
68
+ with CareerLM(api_key="...") as client:
69
+ ...
70
+ ```
71
+
72
+ Full endpoint reference: [careerstudiomax.com/api/docs](https://careerstudiomax.com/api/docs)
@@ -0,0 +1,505 @@
1
+ """
2
+ CareerLM Python SDK
3
+ pip install careerlm
4
+
5
+ from careerlm import CareerLM
6
+ client = CareerLM(api_key="csk_live_v1_your_key_here")
7
+
8
+ score = client.cv.score(cv_text, job_description)
9
+ print(score["ats_score"]) # 87
10
+ """
11
+
12
+ import httpx
13
+ from typing import Optional, List, Dict, Any
14
+
15
+ __version__ = "1.0.0"
16
+ __all__ = ["CareerLM", "CareerLMError"]
17
+
18
+ _BASE_URL = "https://careerlm-api.careerstudiomax.com/v1"
19
+
20
+
21
+ class CareerLMError(Exception):
22
+ """Raised when the CareerLM API returns an error response."""
23
+ def __init__(self, message: str, code: str = "api_error", status: int = 500):
24
+ super().__init__(message)
25
+ self.code = code
26
+ self.status = status
27
+
28
+
29
+ class _Namespace:
30
+ """Base class for API namespaces."""
31
+ def __init__(self, client: "CareerLM"):
32
+ self._c = client
33
+
34
+ def _post(self, endpoint: str, **kwargs) -> Dict[str, Any]:
35
+ return self._c._post(endpoint, **kwargs)
36
+
37
+ def _get(self, endpoint: str) -> Dict[str, Any]:
38
+ return self._c._get(endpoint)
39
+
40
+ def _delete(self, endpoint: str) -> Dict[str, Any]:
41
+ return self._c._delete(endpoint)
42
+
43
+
44
+ class _CV(_Namespace):
45
+ def score(
46
+ self,
47
+ cv_text: str,
48
+ job_description: Optional[str] = None,
49
+ *,
50
+ target_role: Optional[str] = None,
51
+ target_country: str = "GB",
52
+ include_suggestions: bool = True,
53
+ include_keywords: bool = True,
54
+ format: str = "detailed",
55
+ **kwargs,
56
+ ) -> Dict[str, Any]:
57
+ """Score a CV against a job description.
58
+
59
+ Returns ats_score, grade, keyword_match, section_scores, top_suggestions.
60
+
61
+ Example:
62
+ score = client.cv.score(cv_text, job_desc, target_role="Senior Engineer")
63
+ print(score["ats_score"]) # 87
64
+ print(score["grade"]) # "B+"
65
+ """
66
+ return self._post(
67
+ "/career/cv/score",
68
+ cv_text=cv_text,
69
+ job_description=job_description,
70
+ target_role=target_role,
71
+ target_country=target_country,
72
+ options=dict(
73
+ include_suggestions=include_suggestions,
74
+ include_keywords=include_keywords,
75
+ format=format,
76
+ **kwargs,
77
+ ),
78
+ )
79
+
80
+ def optimise(
81
+ self,
82
+ cv_text: str,
83
+ job_description: Optional[str] = None,
84
+ *,
85
+ target_role: Optional[str] = None,
86
+ target_country: str = "GB",
87
+ rewrite_level: str = "moderate",
88
+ preserve_voice: bool = True,
89
+ add_metrics: bool = True,
90
+ **kwargs,
91
+ ) -> Dict[str, Any]:
92
+ """Rewrite and optimise a CV for a target role.
93
+
94
+ Requires Starter tier or above.
95
+
96
+ Returns optimised_cv, changes, before_score, after_score.
97
+
98
+ Example:
99
+ result = client.cv.optimise(cv_text, jd, target_role="Data Engineer")
100
+ print(result["after_score"]) # 91
101
+ """
102
+ return self._post(
103
+ "/career/cv/optimise",
104
+ cv_text=cv_text,
105
+ job_description=job_description,
106
+ target_role=target_role,
107
+ target_country=target_country,
108
+ options=dict(
109
+ rewrite_level=rewrite_level,
110
+ preserve_voice=preserve_voice,
111
+ add_metrics=add_metrics,
112
+ **kwargs,
113
+ ),
114
+ )
115
+
116
+
117
+ class _Salary(_Namespace):
118
+ def benchmark(
119
+ self,
120
+ role: str,
121
+ country: str = "GB",
122
+ *,
123
+ city: Optional[str] = None,
124
+ years_experience: int = 0,
125
+ skills: Optional[List[str]] = None,
126
+ company_size: Optional[str] = None,
127
+ currency: Optional[str] = None,
128
+ include_equity: bool = False,
129
+ include_benefits: bool = False,
130
+ **kwargs,
131
+ ) -> Dict[str, Any]:
132
+ """Benchmark salary across 196 countries with PPP adjustment.
133
+
134
+ Requires Starter tier or above.
135
+
136
+ Returns salary_range (low/median/high/top_10_percent), usd_equivalent,
137
+ skill_premiums, negotiation_target, negotiation_script.
138
+
139
+ Example:
140
+ s = client.salary.benchmark("Data Engineer", "NG",
141
+ city="Lagos", currency="NGN")
142
+ print(s["salary_range"]["median"]) # 6800000
143
+ """
144
+ options: Dict[str, Any] = {}
145
+ if currency: options["currency"] = currency
146
+ if include_equity: options["include_equity"] = include_equity
147
+ if include_benefits: options["include_benefits"] = include_benefits
148
+ options.update(kwargs)
149
+ return self._post(
150
+ "/career/salary/benchmark",
151
+ role=role,
152
+ country=country,
153
+ city=city,
154
+ years_experience=years_experience,
155
+ skills=skills or [],
156
+ company_size=company_size,
157
+ options=options or None,
158
+ )
159
+
160
+
161
+ class _CoverLetter(_Namespace):
162
+ """Generate cover letters in 15 professional modes."""
163
+
164
+ MODES = {
165
+ 1: "Achievement-led", 2: "Insight-led", 3: "Problem-solution",
166
+ 4: "Narrative arc", 5: "Company-specific", 6: "Question-led",
167
+ 7: "Bold statement", 8: "Data-driven", 9: "Cultural fit",
168
+ 10: "Career transition", 11: "Promotion-within", 12: "Referral",
169
+ 13: "Remote confidence", 14: "Multilingual", 15: "Executive gravitas",
170
+ }
171
+
172
+ def generate(
173
+ self,
174
+ cv_text: Optional[str] = None,
175
+ job_description: Optional[str] = None,
176
+ *,
177
+ mode: int = 1,
178
+ company_name: Optional[str] = None,
179
+ candidate_name: Optional[str] = None,
180
+ target_country: str = "GB",
181
+ tone: str = "confident",
182
+ word_limit: int = 280,
183
+ **kwargs,
184
+ ) -> Dict[str, Any]:
185
+ """Generate a cover letter in one of 15 professional modes.
186
+
187
+ Requires Starter tier or above.
188
+
189
+ Modes:
190
+ 1 Achievement-led 2 Insight-led 3 Problem-solution
191
+ 4 Narrative arc 5 Company-specific 6 Question-led
192
+ 7 Bold statement 8 Data-driven 9 Cultural fit
193
+ 10 Career transition 11 Promotion-within 12 Referral
194
+ 13 Remote confidence 14 Multilingual 15 Executive gravitas
195
+
196
+ Example:
197
+ letter = client.cover_letter.generate(
198
+ cv_text, jd,
199
+ mode=5, company_name="Paystack", tone="confident"
200
+ )
201
+ print(letter["content"])
202
+ """
203
+ if not 1 <= mode <= 15:
204
+ raise CareerLMError("mode must be between 1 and 15", "invalid_mode", 400)
205
+ return self._post(
206
+ "/career/cover-letter/generate",
207
+ cv_text=cv_text,
208
+ job_description=job_description,
209
+ mode=mode,
210
+ company_name=company_name,
211
+ candidate_name=candidate_name,
212
+ target_country=target_country,
213
+ tone=tone,
214
+ options={"word_limit": word_limit, **kwargs},
215
+ )
216
+
217
+
218
+ class _Job(_Namespace):
219
+ def match(
220
+ self,
221
+ candidate: Dict[str, Any],
222
+ job: Dict[str, Any],
223
+ ) -> Dict[str, Any]:
224
+ """Score how well a candidate matches a job.
225
+
226
+ Args:
227
+ candidate: { cv_text?, skills, years_experience, location, salary_expectation? }
228
+ job: { title, description?, required_skills, salary_min?, salary_max?,
229
+ location?, remote? }
230
+
231
+ Returns overall_score, grade, dimensions, gaps, strengths, interview_probability,
232
+ apply_recommendation.
233
+
234
+ Example:
235
+ result = client.job.match(
236
+ candidate={"skills": ["Python","SQL"], "years_experience": 5},
237
+ job={"title": "Data Engineer", "required_skills": ["Python","Spark","dbt"]}
238
+ )
239
+ print(result["interview_probability"]) # 0.72
240
+ """
241
+ return self._post("/career/job/match", candidate=candidate, job=job)
242
+
243
+
244
+ class _Interview(_Namespace):
245
+ def questions(
246
+ self,
247
+ role: str,
248
+ *,
249
+ company: Optional[str] = None,
250
+ interview_type: str = "behavioural",
251
+ cv_text: Optional[str] = None,
252
+ count: int = 10,
253
+ include_answers: bool = True,
254
+ seniority: str = "mid",
255
+ **kwargs,
256
+ ) -> Dict[str, Any]:
257
+ """Generate tailored interview questions with model answers.
258
+
259
+ Requires Starter tier or above.
260
+
261
+ Args:
262
+ role: Target job role
263
+ company: Specific company (makes questions more targeted)
264
+ interview_type: "behavioural" | "technical" | "case" | "all"
265
+ count: Number of questions (max 20)
266
+ seniority: "junior" | "mid" | "senior" | "director"
267
+
268
+ Example:
269
+ qs = client.interview.questions(
270
+ "Product Manager", company="Spotify",
271
+ interview_type="behavioural", count=10
272
+ )
273
+ """
274
+ return self._post(
275
+ "/career/interview/questions",
276
+ role=role,
277
+ company=company,
278
+ interview_type=interview_type,
279
+ cv_text=cv_text,
280
+ count=min(count, 20),
281
+ include_answers=include_answers,
282
+ seniority=seniority,
283
+ **kwargs,
284
+ )
285
+
286
+
287
+ class _Skills(_Namespace):
288
+ def gap(
289
+ self,
290
+ current_skills: List[str],
291
+ target_role: str,
292
+ *,
293
+ target_country: str = "GB",
294
+ years_to_achieve: int = 12,
295
+ current_salary: Optional[int] = None,
296
+ include_roi: bool = False,
297
+ include_resources: bool = True,
298
+ currency: str = "GBP",
299
+ **kwargs,
300
+ ) -> Dict[str, Any]:
301
+ """Analyse skill gaps with learning ROI and timeline.
302
+
303
+ Returns readiness_score, gaps (with learn_hours, salary_impact, free_resources),
304
+ estimated_time_to_ready, total_salary_unlock.
305
+
306
+ Example:
307
+ gap = client.skills.gap(
308
+ ["Python", "SQL", "Excel"],
309
+ "Senior Data Scientist",
310
+ target_country="DE",
311
+ currency="EUR",
312
+ include_roi=True,
313
+ )
314
+ print(gap["estimated_time_to_ready"]) # "14 months"
315
+ print(gap["total_salary_unlock"]) # "+€22,000/year"
316
+ """
317
+ return self._post(
318
+ "/career/skills/gap",
319
+ current_skills=current_skills,
320
+ target_role=target_role,
321
+ target_country=target_country,
322
+ years_to_achieve=years_to_achieve,
323
+ current_salary=current_salary,
324
+ options=dict(
325
+ include_roi=include_roi,
326
+ include_resources=include_resources,
327
+ currency=currency,
328
+ **kwargs,
329
+ ),
330
+ )
331
+
332
+
333
+ class _Chat(_Namespace):
334
+ """OpenAI-compatible career chat completions."""
335
+
336
+ class _Completions:
337
+ def __init__(self, client: "CareerLM"):
338
+ self._c = client
339
+
340
+ def create(
341
+ self,
342
+ messages: List[Dict[str, str]],
343
+ *,
344
+ model: str = "careerlm-standard",
345
+ max_tokens: int = 800,
346
+ temperature: float = 0.7,
347
+ **kwargs,
348
+ ) -> Dict[str, Any]:
349
+ """Career-aware chat completions (OpenAI-compatible).
350
+
351
+ Drop-in replacement for openai.chat.completions.create().
352
+
353
+ Example:
354
+ resp = client.chat.completions.create([
355
+ {"role": "user", "content": "How do I negotiate salary?"}
356
+ ])
357
+ print(resp["choices"][0]["message"]["content"])
358
+ """
359
+ return self._c._post(
360
+ "/career/chat/completions",
361
+ messages=messages,
362
+ model=model,
363
+ max_tokens=max_tokens,
364
+ temperature=temperature,
365
+ **kwargs,
366
+ )
367
+
368
+ def __init__(self, client: "CareerLM"):
369
+ super().__init__(client)
370
+ self.completions = self._Completions(client)
371
+
372
+
373
+ class _Context(_Namespace):
374
+ def save(
375
+ self,
376
+ profile: Dict[str, Any],
377
+ context_id: Optional[str] = None,
378
+ ) -> Dict[str, Any]:
379
+ """Save or update a career context for persistent memory across API calls.
380
+
381
+ Example:
382
+ ctx = client.context.save({
383
+ "current_role": "Software Engineer",
384
+ "target_role": "Engineering Manager",
385
+ "skills": ["Python", "Go", "AWS"],
386
+ "country": "GB",
387
+ })
388
+ context_id = ctx["context_id"]
389
+ """
390
+ return self._post("/career/context", profile=profile, context_id=context_id)
391
+
392
+ def get(self, context_id: str) -> Dict[str, Any]:
393
+ """Retrieve a career context by ID."""
394
+ return self._get(f"/career/context/{context_id}")
395
+
396
+ def delete(self, context_id: str) -> Dict[str, Any]:
397
+ """Delete a career context."""
398
+ return self._delete(f"/career/context/{context_id}")
399
+
400
+
401
+ class CareerLM:
402
+ """CareerLM Python SDK — world's first career intelligence API.
403
+
404
+ Usage:
405
+ from careerlm import CareerLM
406
+
407
+ client = CareerLM(api_key="csk_live_v1_your_key_here")
408
+
409
+ # Score a CV
410
+ score = client.cv.score(cv_text, job_description)
411
+ print(score["ats_score"]) # 87
412
+
413
+ # Benchmark salary (196 countries)
414
+ salary = client.salary.benchmark("Data Engineer", "NG",
415
+ city="Lagos", currency="NGN")
416
+ print(salary["salary_range"]["median"]) # 6800000
417
+
418
+ # Generate cover letter
419
+ letter = client.cover_letter.generate(cv_text, jd,
420
+ mode=5, company_name="Paystack")
421
+ print(letter["content"])
422
+
423
+ # Skill gap analysis
424
+ gap = client.skills.gap(["Python", "SQL"], "Senior Data Scientist",
425
+ target_country="DE", include_roi=True)
426
+ print(gap["estimated_time_to_ready"]) # "14 months"
427
+ """
428
+
429
+ def __init__(
430
+ self,
431
+ api_key: str,
432
+ *,
433
+ base_url: str = _BASE_URL,
434
+ timeout: float = 30.0,
435
+ ):
436
+ if not api_key:
437
+ raise CareerLMError(
438
+ "API key is required — get yours free at careerstudiomax.com/api",
439
+ "missing_api_key",
440
+ 0,
441
+ )
442
+ self._api_key = api_key
443
+ self._base_url = base_url.rstrip("/")
444
+ self._http = httpx.Client(
445
+ headers={
446
+ "X-Api-Key": api_key,
447
+ "Content-Type": "application/json",
448
+ "User-Agent": f"careerlm-python/{__version__}",
449
+ },
450
+ timeout=timeout,
451
+ )
452
+ # Namespace instances
453
+ self.cv = _CV(self)
454
+ self.salary = _Salary(self)
455
+ self.cover_letter = _CoverLetter(self)
456
+ self.job = _Job(self)
457
+ self.interview = _Interview(self)
458
+ self.skills = _Skills(self)
459
+ self.chat = _Chat(self)
460
+ self.context = _Context(self)
461
+
462
+ def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]:
463
+ url = f"{self._base_url}{endpoint}"
464
+ # Strip None values so optional params don't pollute the JSON body
465
+ body = {k: v for k, v in kwargs.items() if v is not None} if kwargs else None
466
+ try:
467
+ resp = self._http.request(method, url, json=body)
468
+ except httpx.TimeoutException:
469
+ raise CareerLMError("Request timed out — try a shorter input", "timeout", 504)
470
+ except httpx.ConnectError:
471
+ raise CareerLMError(
472
+ "Could not reach the CareerLM API — check your network connection",
473
+ "connection_error",
474
+ 0,
475
+ )
476
+
477
+ if not resp.is_success:
478
+ try:
479
+ data = resp.json()
480
+ msg = data.get("error", {}).get("message") or "Request failed"
481
+ code = data.get("error", {}).get("code") or "api_error"
482
+ except Exception:
483
+ msg, code = resp.text[:200] or "Request failed", "api_error"
484
+ raise CareerLMError(msg, code, resp.status_code)
485
+
486
+ return resp.json()
487
+
488
+ def _post(self, endpoint: str, **kwargs) -> Dict[str, Any]:
489
+ return self._request("POST", endpoint, **kwargs)
490
+
491
+ def _get(self, endpoint: str) -> Dict[str, Any]:
492
+ return self._request("GET", endpoint)
493
+
494
+ def _delete(self, endpoint: str) -> Dict[str, Any]:
495
+ return self._request("DELETE", endpoint)
496
+
497
+ def close(self):
498
+ """Close the underlying HTTP client."""
499
+ self._http.close()
500
+
501
+ def __enter__(self):
502
+ return self
503
+
504
+ def __exit__(self, *_):
505
+ self.close()
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: careerlm
3
+ Version: 1.0.0
4
+ Summary: Official Python SDK for the CareerLM API — world's first career intelligence API
5
+ Home-page: https://careerstudiomax.com/api/docs
6
+ Author: Career Studio
7
+ Author-email: api@careerstudiomax.com
8
+ Project-URL: Documentation, https://careerstudiomax.com/api/docs
9
+ Project-URL: Source, https://github.com/owolat4real/career-studio
10
+ Project-URL: Bug Tracker, https://github.com/owolat4real/career-studio/issues
11
+ Keywords: career,ai,cv,resume,salary,api,careerlm
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: httpx>=0.24.0
20
+ Dynamic: author
21
+ Dynamic: author-email
22
+ Dynamic: classifier
23
+ Dynamic: description
24
+ Dynamic: description-content-type
25
+ Dynamic: home-page
26
+ Dynamic: keywords
27
+ Dynamic: project-url
28
+ Dynamic: requires-dist
29
+ Dynamic: requires-python
30
+ Dynamic: summary
31
+
32
+ # CareerLM Python SDK
33
+
34
+ Official Python client for the [CareerLM API](https://careerstudiomax.com/api/docs) — world's first career intelligence API.
35
+
36
+ ## Install
37
+
38
+ ```bash
39
+ pip install careerlm
40
+ ```
41
+
42
+ ## Quickstart
43
+
44
+ ```python
45
+ from careerlm import CareerLM
46
+
47
+ client = CareerLM(api_key="csk_live_v1_your_key_here")
48
+
49
+ score = client.cv.score(cv_text, job_description)
50
+ print(score["ats_score"]) # 87
51
+ print(score["grade"]) # "B+"
52
+ ```
53
+
54
+ ## What you can do
55
+
56
+ | Method | Description |
57
+ |---|---|
58
+ | `client.cv.score(cv_text, job_description)` | Score a CV against a job description |
59
+ | `client.cv.optimise(cv_text, job_description)` | Rewrite and optimise a CV for a target role |
60
+ | `client.salary.benchmark(role, country)` | Salary benchmarking across 196 countries, PPP-adjusted |
61
+ | `client.cover_letter.generate(cv_text, job_description, mode=1)` | Generate a cover letter in one of 15 professional modes |
62
+ | `client.job.match(candidate, job)` | Score how well a candidate matches a job |
63
+ | `client.interview.questions(role)` | Tailored interview questions with model answers |
64
+ | `client.skills.gap(current_skills, target_role)` | Skill-gap analysis with learning ROI and timeline |
65
+ | `client.chat.completions.create(messages)` | OpenAI-compatible career chat completions |
66
+ | `client.context.save(profile)` / `.get(id)` / `.delete(id)` | Persistent career context across calls |
67
+
68
+ ## Example: salary benchmark
69
+
70
+ ```python
71
+ salary = client.salary.benchmark("Data Engineer", "NG", city="Lagos", currency="NGN")
72
+ print(salary["salary_range"]["median"]) # 6800000
73
+ ```
74
+
75
+ ## Example: cover letter
76
+
77
+ ```python
78
+ letter = client.cover_letter.generate(
79
+ cv_text, job_description,
80
+ mode=5, company_name="Paystack", tone="confident",
81
+ )
82
+ print(letter["content"])
83
+ ```
84
+
85
+ ## Errors
86
+
87
+ ```python
88
+ from careerlm import CareerLM, CareerLMError
89
+
90
+ try:
91
+ client.cv.score(cv_text, job_description)
92
+ except CareerLMError as e:
93
+ print(e.code, e.status, str(e))
94
+ ```
95
+
96
+ ## Context manager
97
+
98
+ ```python
99
+ with CareerLM(api_key="...") as client:
100
+ ...
101
+ ```
102
+
103
+ Full endpoint reference: [careerstudiomax.com/api/docs](https://careerstudiomax.com/api/docs)
@@ -0,0 +1,8 @@
1
+ README.md
2
+ setup.py
3
+ careerlm/__init__.py
4
+ careerlm.egg-info/PKG-INFO
5
+ careerlm.egg-info/SOURCES.txt
6
+ careerlm.egg-info/dependency_links.txt
7
+ careerlm.egg-info/requires.txt
8
+ careerlm.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ httpx>=0.24.0
@@ -0,0 +1 @@
1
+ careerlm
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,28 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="careerlm",
5
+ version="1.0.0",
6
+ description="Official Python SDK for the CareerLM API — world's first career intelligence API",
7
+ long_description=open("README.md").read() if __import__("os").path.exists("README.md") else "",
8
+ long_description_content_type="text/markdown",
9
+ author="Career Studio",
10
+ author_email="api@careerstudiomax.com",
11
+ url="https://careerstudiomax.com/api/docs",
12
+ project_urls={
13
+ "Documentation": "https://careerstudiomax.com/api/docs",
14
+ "Source": "https://github.com/owolat4real/career-studio",
15
+ "Bug Tracker": "https://github.com/owolat4real/career-studio/issues",
16
+ },
17
+ packages=find_packages(),
18
+ python_requires=">=3.8",
19
+ install_requires=["httpx>=0.24.0"],
20
+ keywords=["career", "ai", "cv", "resume", "salary", "api", "careerlm"],
21
+ classifiers=[
22
+ "Programming Language :: Python :: 3",
23
+ "License :: OSI Approved :: MIT License",
24
+ "Operating System :: OS Independent",
25
+ "Topic :: Software Development :: Libraries :: Python Modules",
26
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
27
+ ],
28
+ )