Metadata-Version: 2.4
Name: resumly
Version: 0.1.0
Summary: Official Python SDK for the Resumly API — create ATS-optimized, tailored resumes programmatically.
Author-email: Resumly <support@resumly.ai>
License: MIT License
        
        Copyright (c) 2026 Resumly
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://resumly.ai
Project-URL: Documentation, https://resumly.ai/docs/api
Project-URL: Repository, https://github.com/resumly/resumly-python
Project-URL: Issues, https://github.com/resumly/resumly-python/issues
Keywords: resume,ats,job-search,api,sdk,career,cover-letter,interview
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Requires-Dist: pydantic>=2.0
Dynamic: license-file

# Resumly Python SDK

Official Python client for the [Resumly API](https://resumly.ai) — full programmatic access to every Resumly feature.

## Installation

```bash
pip install resumly
```

Or install from source:

```bash
cd sdk/
pip install -e .
```

## Quick Start

```python
from resumly import ResumlyClient

client = ResumlyClient(api_key="rly_your_api_key_here")

# Upload your base resume
client.upload_base_resume("my_resume.pdf")

# Create a tailored resume for a job posting
result = client.create_resume(job_url="https://example.com/jobs/12345")
job_id = result["job_id"]

# Get the final resume
resume = client.get_resume(job_id)

# Download as DOCX
client.download_resume(resume["resume_file_path"], path="tailored.docx")

# Run an ATS check on any resume file
ats = client.run_ats_check("my_resume.pdf")
print(ats["report"])
```

## Getting Your API Key

1. Log in to [resumly.ai](https://resumly.ai)
2. Go to **Settings > API Keys**
3. Click **Create New Key** and give it a name
4. Copy the key (shown only once)

## Complete API Reference

### Constructor

```python
ResumlyClient(
    api_key="rly_...",
    base_url="https://api.resumly.ai",  # override for local dev
    timeout=180,                          # seconds
    max_retries=3,                        # auto-retry on 429
)
```

---

### Base Resume

| Method | Description |
|--------|-------------|
| `upload_base_resume(file_path)` | Upload a PDF/DOCX as your base resume |
| `get_base_resume()` | Get the parsed JSON of your base resume |
| `update_base_resume(resume_data)` | Update base resume with new JSON |
| `improve_base_resume(comments)` | AI-improve base resume from feedback |
| `translate_base_resume(target_language)` | Translate base resume |
| `generate_base_resume_docx(resume_data)` | Generate Word doc from base resume |
| `freeze_base_resume_element(path, freeze)` | Freeze/unfreeze a resume element |
| `get_locked_elements()` | Get all locked elements |

### User Profile & Settings

| Method | Description |
|--------|-------------|
| `get_profile()` | Get user profile |
| `update_profile(email, **fields)` | Update profile fields |
| `upload_profile_picture(file_path)` | Upload profile picture |
| `get_user_settings()` | Get all settings |
| `update_user_settings(settings)` | Update settings |
| `reset_style_settings()` | Reset style to defaults |
| `add_always_show_skill(skill)` | Add to always-show skills |
| `remove_always_show_skill(skill)` | Remove from always-show skills |
| `add_never_show_skill(skill)` | Add to never-show skills |
| `remove_never_show_skill(skill)` | Remove from never-show skills |

### Job Preferences

| Method | Description |
|--------|-------------|
| `get_job_preferences()` | Get job preferences |
| `update_job_preferences(preferences)` | Update all preferences |
| `update_job_preference(key, value)` | Update single preference |
| `delete_job_preference(key)` | Delete a preference |

### Autofill & Custom Instructions

| Method | Description |
|--------|-------------|
| `get_autofill_attributes()` | Get autofill attributes |
| `set_autofill_attributes(attributes)` | Set autofill attributes |
| `get_custom_instructions()` | Get custom AI instructions |
| `set_custom_instructions(text)` | Set custom AI instructions |

### Memory

| Method | Description |
|--------|-------------|
| `get_memory()` | Get all memory points |
| `clear_memory()` | Clear all memory |
| `delete_memory_point(index)` | Delete specific memory point |

### Credits & Statistics

| Method | Description |
|--------|-------------|
| `check_credit(email)` | Check credit balance |
| `check_subscription(email)` | Check subscription status |
| `get_statistics(queue_statistics)` | Get user statistics |
| `get_credit_utilization()` | Credit utilization history |
| `get_ai_insights()` | AI insights for resume applications |
| `trigger_ai_insights()` | Recalculate AI insights |
| `get_ai_insights_jobs()` | AI insights for job database |
| `trigger_ai_insights_jobs()` | Recalculate job AI insights |
| `get_application_flow()` | Application flow Sankey data |
| `get_resume_timeline()` | Resume creation timeline |
| `get_resume_distribution()` | Resume distribution analytics |

---

### Tailored Resumes

| Method | Description |
|--------|-------------|
| `create_resume(job_url=..., job_description=..., cover_letter=False, interview_question=False)` | Create tailored resume (auto init+process) |
| `list_recent_resumes(days, favorites_only, queue_only, page, page_size)` | List recent resumes |
| `get_resume(job_id)` | Get final resume JSON |
| `update_resume(job_id, data)` | Update final resume |
| `get_resume_comparison(job_id)` | Base vs tailored comparison |
| `get_resume_metadata(job_id)` | Metadata (company, title, etc.) |
| `get_resume_insights(job_id)` | AI insights for resume |
| `regenerate_insights(job_id)` | Regenerate insights |
| `delete_resume(job_id)` | Delete resume |
| `download_resume(s3_url, path)` | Download DOCX file |
| `export_resume_pdf(job_id, document_type, path)` | Export as PDF |
| `regenerate_resume(job_id)` | Regenerate resume |
| `update_job_info(job_id, **fields)` | Update job info |

### Cover Letter

| Method | Description |
|--------|-------------|
| `create_cover_letter(job_id)` | Generate cover letter |
| `get_cover_letter(job_id)` | Get cover letter |
| `update_cover_letter(job_id, data)` | Update cover letter |
| `regenerate_cover_letter(job_id)` | Regenerate cover letter |

### Interview Questions

| Method | Description |
|--------|-------------|
| `create_interview_questions(job_id)` | Generate interview questions |
| `get_interview_questions(job_id)` | Get interview questions |
| `check_interview_answer(job_id, question, answer)` | Check an answer |

### Resume Actions

| Method | Description |
|--------|-------------|
| `rephrase_resume(job_id, text)` | Rephrase content |
| `translate_resume(job_id, target_language)` | Translate resume |
| `improve_resume(job_id, user_comment)` | AI-improve resume |
| `chat_with_resume(job_id, message)` | AI chat editing |
| `generate_bullet_points(**kwargs)` | Generate bullet points |
| `rephrase_text(text)` | Rephrase any text |

### Favorites & Queue

| Method | Description |
|--------|-------------|
| `favorite_resume(job_id)` | Toggle favorite |
| `unfavorite_resume(job_id)` | Remove favorite |
| `add_to_queue(job_id)` | Add to queue |
| `remove_from_queue(job_id)` | Remove from queue |
| `get_auto_apply_resumes()` | Get auto-apply eligible |

### Public Links (Share)

| Method | Description |
|--------|-------------|
| `create_public_link(job_id, **settings)` | Create shareable link |
| `get_public_link(job_id)` | Get link info |
| `update_public_link(job_id, **settings)` | Update link settings |
| `delete_public_link(job_id)` | Delete link |

### Company Research

| Method | Description |
|--------|-------------|
| `research_company(job_id)` | Trigger company research |
| `get_company_research(job_id)` | Get research results |

### Autofill & Feedback

| Method | Description |
|--------|-------------|
| `autofill_application(job_id, fields)` | Autofill job application |
| `submit_autofill_feedback(job_id, feedback)` | Submit autofill feedback |
| `save_change_summary(job_id, summary)` | Save change summary |
| `get_change_summaries(job_id)` | Get change summaries |
| `submit_feedback(job_id, feedback)` | Submit resume feedback |

### Email

| Method | Description |
|--------|-------------|
| `send_resume_email(job_id, **kwargs)` | Send resume via email |

---

### Batch Operations

| Method | Description |
|--------|-------------|
| `init_batch(job_urls, job_descriptions)` | Initialize batch |
| `process_batch(batch_id)` | Start processing |
| `get_batch(batch_id)` | Get batch status |
| `list_batches()` | List all batches |
| `get_batch_resumes(batch_id)` | Get resumes in batch |

---

### Job Search

| Method | Description |
|--------|-------------|
| `generate_job_search_query()` | Generate query from resume |
| `generate_and_run_search()` | Generate + run immediately |
| `run_job_search(query_id)` | Run a search |
| `get_search_queries()` | List all queries |
| `create_search_query(query)` | Create query |
| `update_search_query(query_id, query)` | Update query |
| `delete_search_query(query_id)` | Delete query |
| `get_relevant_jobs()` | Get relevant jobs |
| `get_job_status_stats()` | Status statistics |
| `get_job(job_id)` | Get job details |
| `get_related_jobs(job_id)` | Get related jobs |
| `save_job(job_id, save)` | Save/unsave job |
| `block_job(job_id, block)` | Block/unblock job |
| `skip_job(job_id, skip)` | Skip/unskip job |
| `reset_skipped_jobs()` | Reset all skipped |
| `embed_base_resume()` | Create resume embeddings |

### Job Search Agents

| Method | Description |
|--------|-------------|
| `create_search_agent(agent)` | Create agent |
| `update_search_agent(agent_id, agent)` | Update agent |
| `get_search_agents()` | List agents |
| `delete_search_agent(agent_id)` | Delete agent |
| `parse_and_store_job(raw_text)` | Parse raw job text |

### Job Match

| Method | Description |
|--------|-------------|
| `get_job_match_score(job_description, job_url)` | Get match score |

---

### Templates

| Method | Description |
|--------|-------------|
| `list_templates()` | List all template types |
| `list_standard_templates()` | List standard templates |
| `get_standard_template(id)` | Get standard template |
| `list_my_templates()` | List user template instances |
| `create_base_template(template_id)` | Create base template |
| `list_base_templates()` | List base templates |
| `get_base_template(id)` | Get base template |
| `update_base_template_html(id, html)` | Update template HTML |
| `reset_base_template(id)` | Reset template |
| `revise_base_template(id, feedback)` | AI revise template |
| `delete_base_template(id)` | Delete template |
| `create_resume_template(job_id, template_id)` | Create for resume |
| `list_resume_templates(job_id)` | List for resume |
| `get_resume_template(job_id, id)` | Get for resume |
| `update_resume_template_html(job_id, id, html)` | Update HTML |
| `reset_resume_template(job_id, id)` | Reset |
| `revise_resume_template(job_id, id, feedback)` | AI revise |
| `delete_resume_template(job_id, id)` | Delete |
| `render_template(job_id, template_id)` | Render template |
| `compress_content(job_id)` | Compress to fit |
| `convert_template_to_pdf(html)` | HTML to PDF |

---

### LinkedIn

| Method | Description |
|--------|-------------|
| `upload_linkedin_profile(profile_data)` | Upload profile |
| `optimize_linkedin_profile()` | AI optimization |
| `get_linkedin_profile()` | Get stored profile |

---

### Free Tools

All tools accept a resume file path, process it, and return a report.

| Method | Description |
|--------|-------------|
| `run_ats_check(file_path)` | ATS compatibility check |
| `run_resume_roast(file_path)` | Brutally honest roast |
| `run_career_clock(file_path)` | Career clock analysis |
| `run_interview_questions_tool(file_path)` | Interview questions |
| `run_career_personality_test(file_path)` | Personality test |
| `run_skills_gap_analyzer(file_path)` | Skills gap analysis |
| `run_readability_test(file_path)` | Readability test |
| `run_linkedin_profile_generator(file_path)` | LinkedIn generator |
| `run_buzzword_detector(file_path)` | Buzzword detection |
| `run_job_search_keywords(file_path)` | Search keywords |
| `run_networking_copilot(file_path)` | Networking strategy |

Each tool also has a `get_*_report(analysis_id)` method to retrieve a previous report.

---

### Personalized Learning

| Method | Description |
|--------|-------------|
| `create_course(**kwargs)` | Create a course |
| `list_courses()` | List courses |
| `get_course(course_id)` | Get course |
| `revise_slide(course_id, **kwargs)` | Revise a slide |
| `create_mindmap(course_id)` | Create mindmap |
| `clarify_course(course_id, message)` | Ask question |

### Website Resume (Portfolio)

| Method | Description |
|--------|-------------|
| `list_website_styles()` | Available styles |
| `create_website_resume(**kwargs)` | Generate portfolio |
| `list_website_resumes()` | List portfolios |
| `get_website_resume(id)` | Get portfolio |
| `regenerate_website_resume(id, style_id)` | New style |
| `revise_website_resume(id, feedback)` | AI revise |
| `reset_website_resume(id)` | Reset to original |
| `update_website_resume_html(id, html)` | Save HTML |
| `delete_website_resume(id)` | Delete |

### Affiliate

| Method | Description |
|--------|-------------|
| `create_affiliate_code()` | Create code |
| `get_affiliate_stats()` | Get stats |
| `get_affiliate_transactions()` | Transaction history |
| `request_affiliate_payout()` | Request payout |

### Other

| Method | Description |
|--------|-------------|
| `customer_service_chat(message)` | Chat with support bot |
| `transcribe_audio(file_path)` | Transcribe audio |
| `report_bug(**kwargs)` | Report a bug |
| `get_latest_announcement()` | Latest announcement |
| `delete_account()` | Delete your account |

---

## Error Handling

```python
from resumly import ResumlyClient, RateLimitError, InsufficientCreditsError

client = ResumlyClient(api_key="rly_...")

try:
    resume = client.create_resume(job_url="https://example.com/job")
except RateLimitError as e:
    print(f"Slow down! Retry after {e.retry_after}s")
except InsufficientCreditsError:
    print("Out of credits — upgrade your plan")
```

The client auto-retries on 429 (rate limit) up to `max_retries` times.

| Exception | HTTP Code | When |
|-----------|-----------|------|
| `AuthenticationError` | 401 | Invalid or missing API key |
| `InsufficientCreditsError` | 403 | Not enough credits |
| `NotFoundError` | 404 | Resource not found |
| `ValidationError` | 422 | Invalid request |
| `RateLimitError` | 429 | Too many requests |
| `ResumlyError` | * | Any other error |

## Rate Limits

- **60 requests per minute**
- **1,000 requests per day**

## License

MIT
