aiondtech 2.5.0
Official Python SDK for AiondTech Resume Analyser API
License: MIT
Requires Python: >=3.8
Keywords: aiondtech, resume, cv, parser, analyzer, ats, recruitment, hr, api, sdk

# AiondTech Resume Analyser SDK

Official Python SDK for the [AiondTech Resume Analyser API](https://aiondtech.com).

[![PyPI version](https://badge.fury.io/py/aiondtech.svg)](https://badge.fury.io/py/aiondtech)
[![Python Versions](https://img.shields.io/pypi/pyversions/aiondtech.svg)](https://pypi.org/project/aiondtech/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Installation

```bash
pip install aiondtech
```

## Quick Start

```python
from aiondtech import ResumeAnalyser

# Initialize client
client = ResumeAnalyser(api_key="your-api-key")

# Or use environment variable
# export AIONDTECH_API_KEY="your-api-key"
client = ResumeAnalyser()

# Production mode
client = ResumeAnalyser(api_key="your-api-key", production=True)
```

### Constructor Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `api_key` | `str` | `None` | API key (or set `AIONDTECH_API_KEY` env var) |
| `base_url` | `str` | `None` | Custom API base URL |
| `timeout` | `int` | `120` | Request timeout in seconds |
| `production` | `bool` | `False` | Use production URL (`https://api.aiondtech.com`) |

---

## API Endpoints

Credit usage varies depending on resume size and complexity. Every response includes the actual `credits_used` — always check it for accurate tracking.

| Method | Credits | Description |
|--------|---------|-------------|
| `resumes.upload()` | Varies | Upload PDF resume |
| `resumes.upload_and_analyze()` | Varies | Upload + AI parsing |
| `resumes.upload_analyze_compare()` | Varies | Upload + parse + compare to job |
| `resumes.analyze()` | Varies | Parse existing resume by ID |
| `resumes.compare_resumes()` | Varies | Compare resume to job |
| `resumes.list()` | 0 | List all resumes |
| `jobs.create()` | Varies | Create job posting |
| `jobs.list()` | 0 | List all jobs |
| `credits.balance()` | 0 | Check credit balance |
| `credits.usage()` | 0 | View usage history |

---

## Detailed Usage

### 1. Upload Resume

Upload a PDF resume without parsing. Returns a `resume_id` for later use.

```python
result = client.resumes.upload("path/to/resume.pdf")

print(f"Resume ID: {result.resume_id}")
print(f"Message: {result.message}")
print(f"Credits Used: {result.credits_used}")
```

**Output:**

```
Resume ID: 450
Message: Resume uploaded successfully
Credits Used: 1
```

---

### 2. Upload and Analyze Resume

Upload a PDF and immediately extract structured data (AI-powered parsing).

```python
result = client.resumes.upload_and_analyze("path/to/resume.pdf")

print(f"Resume ID: {result.resume_id}")
print(f"Full Name: {result.full_name}")
print(f"Email: {result.email}")
print(f"Skills: {result.skills}")
print(f"Job Titles: {result.job_titles}")
print(f"Total Experience: {result.total_experience}")
print(f"Credits Used: {result.credits_used}")
print(f"Parsed Data: {result.parsed_data}")
```

**Output:**

```
Resume ID: 450
Full Name: John Doe
Email: john@example.com
Skills: ['Python', 'Django', 'AWS']
Job Titles: ['Senior Developer', 'Tech Lead']
Total Experience: 8 years
Credits Used: 5
Parsed Data: {'full_name': 'John Doe', 'email': 'john@example.com', ...}
```

**Full `parsed_data` structure:**

```python
{
    "full_name": "John Doe",
    "email": "john@example.com",
    "contact_number": "+1234567890",
    "linkedin": "linkedin.com/in/johndoe",
    "location": "New York, NY",
    "skills": ["Python", "Django", "AWS"],
    "job_titles": ["Senior Developer", "Tech Lead"],
    "companies": ["Google", "Meta"],
    "education": ["BSc Computer Science - MIT"],
    "total_experience": "8 years",
    "certifications": ["AWS Certified Solutions Architect"],
    "summary": "Experienced software engineer..."
}
```

---

### 3. Upload, Analyze, and Compare

Upload a resume, parse it, and compare against a job posting in one call.

```python
result = client.resumes.upload_analyze_compare("resume.pdf", job_id=56)

print(f"Resume ID: {result.resume_id}")
print(f"Job ID: {result.job_id}")
print(f"Score: {result.comparison_score}")
print(f"Reason: {result.comparison_reason}")
print(f"Parsed Data: {result.parsed_data}")
print(f"Credits Used: {result.credits_used}")
```

**Output:**

```
Resume ID: 449
Job ID: 56
Score: 30
Reason: The candidate has a strong technical background...
Parsed Data: {'full_name': 'Salem O. Ba Atya', 'email': 'Baatyaso@gmail.com', ...}
Credits Used: 9
```

---

### 4. Analyze Resume by ID

Parse an already-uploaded resume by its ID.

```python
result = client.resumes.analyze(resume_id=444)

print(f"Resume ID: {result.resume_id}")
print(f"Partner: {result.partner}")
print(f"Full Name: {result.full_name}")
print(f"Email: {result.email}")
print(f"Phone: {result.phone}")
print(f"LinkedIn: {result.linkedin}")
print(f"Location: {result.location}")
print(f"Skills: {result.skills}")
print(f"Job Titles: {result.job_titles}")
print(f"Companies: {result.companies}")
print(f"Education: {result.education}")
print(f"Total Experience: {result.total_experience}")
print(f"Certifications: {result.certifications}")
print(f"Credits Used: {result.credits_used}")
print(f"Parsed Data: {result.parsed_data}")
```

**Output:**

```
Resume ID: 444
Partner: your-partner-id
Full Name: John Doe
Email: john@example.com
Phone: +1234567890
LinkedIn: linkedin.com/in/johndoe
Location: New York, NY
Skills: ['Python', 'Django', 'AWS']
Job Titles: ['Senior Developer', 'Tech Lead']
Companies: ['Google', 'Meta']
Education: ['BSc Computer Science - MIT']
Total Experience: 8 years
Certifications: ['AWS Certified Solutions Architect']
Credits Used: 4
Parsed Data: {'full_name': 'John Doe', ...}
```

---

### 5. Create Job Posting

Create a new job posting to compare resumes against.

```python
job = client.jobs.create(
    title="Senior Python Developer",
    description="We are looking for an experienced Python developer..."
)

print(f"Job ID: {job.job_id}")
print(f"Title: {job.title}")
print(f"Description: {job.description}")
print(f"Created By: {job.created_by}")
print(f"Created At: {job.created_at}")
print(f"Credits Used: {job.credits_used}")
```

**Output:**

```
Job ID: 57
Title: Senior Python Developer
Description: We are looking for an experienced Python developer...
Created By: your-partner-id
Created At: 2026-02-06T10:30:00Z
Credits Used: 1
```

---

### 6. Compare Resume to Job

Compare an existing resume against an existing job posting.

```python
result = client.resumes.compare_resumes(resume_id=445, job_id=56)

print(f"Resume ID: {result.resume_id}")
print(f"Job ID: {result.job_id}")
print(f"Score: {result.comparison_score}")
print(f"Reason: {result.comparison_reason}")
print(f"Language: {result.language}")
print(f"Credits Used: {result.credits_used}")
```

**Output:**

```
Resume ID: 445
Job ID: 56
Score: 75
Reason: The candidate demonstrates strong alignment with the role requirements...
Language: en
Credits Used: 5
```

---

### 7. List Resumes

List all uploaded resumes with pagination.

```python
result = client.resumes.list(page=1, limit=50)

print(f"Total: {result.total}")
print(f"Page: {result.page}")
print(f"Limit: {result.limit}")
print(f"Has More: {result.has_more}")
print(f"Count: {len(result)}")

for resume in result:
    print(f"  ID: {resume['id']}, Name: {resume.get('full_name')}, File: {resume.get('filename')}")
```

**Output:**

```
Total: 120
Page: 1
Limit: 50
Has More: True
Count: 50
  ID: 450, Name: John Doe, File: resume.pdf
  ID: 449, Name: Salem O. Ba Atya, File: Salem_20220524.pdf
  ...
```

---

### 8. List Jobs

List all job postings with pagination.

```python
result = client.jobs.list(page=1, limit=50)

print(f"Total: {result.total}")
print(f"Page: {result.page}")
print(f"Limit: {result.limit}")
print(f"Has More: {result.has_more}")
print(f"Count: {len(result)}")

for job in result:
    print(f"  ID: {job['id']}, Title: {job['title']}")
```

**Output:**

```
Total: 10
Page: 1
Limit: 50
Has More: False
Count: 10
  ID: 56, Title: Senior Python Developer
  ID: 55, Title: Data Scientist
  ...
```

---

### 9. Check Credit Balance

```python
balance = client.credits.balance()

print(f"Total Credits: {balance.get('total_credits')}")
print(f"Used Credits: {balance.get('used_credits')}")
print(f"Remaining Credits: {balance.get('remaining_credits')}")
print(f"Daily Limit: {balance.get('daily_limit')}")
print(f"Used Today: {balance.get('used_today')}")
print(f"Credits Today: {balance.get('credits_today')}")
print(f"Period Start: {balance.get('period_start')}")
print(f"Period End: {balance.get('period_end')}")
```

**Output:**

```
Total Credits: 3500.0
Used Credits: 123
Remaining Credits: 3377.0
Daily Limit: 300.0
Used Today: 36
Credits Today: 70
Period Start: 2026-02-01
Period End: 2026-02-28
```

---

### 10. Credit Usage History

```python
usage = client.credits.usage()

print(f"Total Credits Used: {usage.get('total_credits')}")
print(f"Base Credits: {usage.get('base_credits')}")
print(f"AI Credits: {usage.get('gpt_credits')}")
print(f"Record Count: {usage.get('record_count')}")

# Print last 5 entries
for entry in usage.get('history', [])[:5]:
    print(f"  {entry['timestamp']} | {entry['endpoint']} | {entry['credits_used']} credits (base: {entry['base_credits']}, ai: {entry['gpt_credits']})")
```

**Output:**

```
Total Credits Used: 123
Base Credits: 75
AI Credits: 48
Record Count: 69
  2026-02-05T23:14:52 | /external/credits/balance | 0 credits (base: 0, ai: 0)
  2026-02-05T23:03:57 | /external/upload-resume-analyze-compare | 9 credits (base: 5, ai: 4)
  2026-02-05T23:02:20 | /external/upload-resume-analyze | 5 credits (base: 3, ai: 2)
  2026-02-05T23:01:21 | /external/upload-resume | 1 credits (base: 1, ai: 0)
  2026-02-05T23:06:23 | /external/create-job | 1 credits (base: 1, ai: 0)
```

**With date filters:**

```python
usage = client.credits.usage(start_date="2026-02-01", end_date="2026-02-28")
print(f"Total Credits Used: {usage.get('total_credits')}")
```

---

## Error Handling

```python
from aiondtech import (
    ResumeAnalyser,
    APIError,
    AuthenticationError,
    InsufficientCreditsError,
    ValidationError,
    NotFoundError,
    RateLimitError,
)

client = ResumeAnalyser(api_key="your-api-key")

try:
    result = client.resumes.upload_and_analyze("resume.pdf")
except AuthenticationError as e:
    print(f"Invalid API key: {e}")
except InsufficientCreditsError as e:
    print(f"Not enough credits: {e}")
    print(f"Remaining: {e.credits_remaining}")
    print(f"Required: {e.credits_required}")
except ValidationError as e:
    print(f"Invalid input: {e}")
except NotFoundError as e:
    print(f"Resource not found: {e}")
except RateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after} seconds")
except APIError as e:
    print(f"API error [{e.status_code}]: {e.message}")
```

---

## Complete Workflow Example

```python
from aiondtech import ResumeAnalyser

client = ResumeAnalyser(api_key="your-api-key")

# Step 1: Create a job posting
job = client.jobs.create(
    title="Senior Python Developer",
    description="5+ years Python, Django, AWS, PostgreSQL required..."
)
print(f"Created job #{job.job_id}: {job.title} ({job.credits_used} credits)")

# Step 2: Upload and analyze a resume
analysis = client.resumes.upload_and_analyze("candidate_resume.pdf")
print(f"Candidate: {analysis.full_name}")
print(f"Skills: {', '.join(analysis.skills)}")
print(f"Experience: {analysis.total_experience}")
print(f"Credits used: {analysis.credits_used}")

# Step 3: Compare resume to job
comparison = client.resumes.compare_resumes(
    resume_id=analysis.resume_id,
    job_id=job.job_id
)
print(f"Score: {comparison.comparison_score}%")
print(f"Reasoning: {comparison.comparison_reason}")
print(f"Credits used: {comparison.credits_used}")

# Step 4: Check remaining credits
balance = client.credits.balance()
print(f"Credits remaining: {balance['remaining_credits']}")
```

### One-Step Workflow (Upload + Analyze + Compare)

```python
result = client.resumes.upload_analyze_compare("resume.pdf", job_id=job.job_id)
print(f"Score: {result.comparison_score}% — {result.comparison_reason}")
print(f"Credits used: {result.credits_used}")
```

### Batch Processing

```python
import os

job = client.jobs.create("Data Scientist", "ML, Python, statistics...")

total_credits = job.credits_used
results = []

for pdf in os.listdir("resumes/"):
    if pdf.endswith(".pdf"):
        r = client.resumes.upload_analyze_compare(
            f"resumes/{pdf}", job_id=job.job_id
        )
        results.append(r)
        total_credits += r.credits_used
        print(f"{r.comparison_score:5.1f}% — {pdf} ({r.credits_used} credits)")

# Sort by score
results.sort(key=lambda x: x.comparison_score, reverse=True)
print(f"\nTop candidate: resume_id={results[0].resume_id} ({results[0].comparison_score}%)")
print(f"Total credits used: {total_credits}")
```

---

## Environment Variables

```bash
# Set your API key
export AIONDTECH_API_KEY="your-api-key"

# Optional: Custom base URL
export AIONDTECH_BASE_URL="https://api.aiondtech.com"
```

```python
from aiondtech import ResumeAnalyser

# Client automatically uses environment variables
client = ResumeAnalyser()
```

---

## Support

- **Documentation**: [https://docs.aiondtech.com](https://docs.aiondtech.com)
- **API Reference**: [https://api.aiondtech.com/docs](https://api.aiondtech.com/docs)
- **Email**: support@aiondtech.com
- **Issues**: [GitHub Issues](https://github.com/aiondtech/aiondtech-python/issues)

## License

MIT License - see [LICENSE](LICENSE) for details.