Version: 0.2.0
Base URL (Development): http://localhost:3001
Base URL (Production): https://api.inmidstmylife.com
The In Midst My Life API provides a RESTful interface for managing dynamic, mask-based CVs and résumés. The system supports:
Most endpoints require JWT bearer token authentication. Include the token in the Authorization header:
Authorization: Bearer <your-jwt-token>
Tokens include permission claims for fine-grained access control. Obtain tokens via your authentication provider or identity service.
Unauthenticated Endpoints:
GET /healthGET /readyGET /openapi.yamlAccess interactive API documentation with live testing capabilities:
http://localhost:3001/docs
The Swagger UI provides:
Alternative documentation interface with improved readability:
http://localhost:3001/redoc
Redoc offers:
Download the raw OpenAPI YAML specification:
curl http://localhost:3001/openapi.yaml > openapi.yaml
Two specifications are available:
/openapi.yaml (Core CV/Mask functionality)/openapi-hunter.yaml (Job search automation)GET /health
Returns API health status (always succeeds if server is running).
Response:
{
"status": "ok"
}
GET /ready
Checks if all dependencies (database, cache, etc.) are healthy.
Response (200):
{
"status": "ready"
}
Response (503):
{
"status": "degraded",
"checks": {
"database": "healthy",
"cache": "unhealthy"
}
}
GET /metrics
Returns Prometheus-compatible metrics for monitoring.
Response:
# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="GET",route="/profiles",status="200"} 1247
...
⚠️ Security Note: Restrict /metrics endpoint in production via ingress auth or IP allowlist.
GET /profiles
Retrieve all profiles for the authenticated user.
Query Parameters:
limit (integer, optional): Maximum number of results (default: 50, max: 100)offset (integer, optional): Pagination offset (default: 0)Response:
{
"profiles": [
{
"id": "uuid",
"slug": "john-doe",
"displayName": "John Doe",
"title": "Software Engineer",
"isActive": true,
"createdAt": "2025-01-01T00:00:00Z"
}
],
"total": 1,
"limit": 50,
"offset": 0
}
GET /profiles/{id}
Retrieve a specific profile by ID.
Response:
{
"id": "uuid",
"identityId": "uuid",
"slug": "john-doe",
"displayName": "John Doe",
"title": "Software Engineer",
"headline": "Building scalable systems",
"summaryMarkdown": "Experienced engineer...",
"avatarUrl": "https://example.com/avatar.jpg",
"locationText": "San Francisco, CA",
"isActive": true,
"createdAt": "2025-01-01T00:00:00Z",
"updatedAt": "2025-01-15T00:00:00Z"
}
POST /profiles
Content-Type: application/json
Request Body:
{
"slug": "john-doe",
"displayName": "John Doe",
"title": "Software Engineer",
"headline": "Building scalable systems",
"summaryMarkdown": "Experienced engineer with 10+ years...",
"locationText": "San Francisco, CA"
}
Response (201):
{
"id": "uuid",
"slug": "john-doe",
"displayName": "John Doe",
...
}
PATCH /profiles/{id}
Content-Type: application/json
Request Body (partial):
{
"title": "Senior Software Engineer",
"headline": "Leading distributed systems"
}
DELETE /profiles/{id}
Soft deletes a profile (sets isActive: false).
Response (204): No content
POST /profiles/{id}/masks/select
Content-Type: application/json
Selects the best masks for a profile based on contexts and tags.
Request Body:
{
"contexts": ["design", "leadership"],
"tags": ["impact", "innovation"],
"limit": 5
}
Response:
{
"masks": [
{
"id": "mask-architect",
"name": "Architect",
"ontology": "cognitive-synthesis",
"relevanceScore": 0.95
}
]
}
POST /profiles/{id}/narrative
Content-Type: application/json
Generates AI-powered narrative blocks for résumé.
Request Body:
{
"contexts": ["technical"],
"tags": ["backend", "distributed-systems"],
"timeline": [
{
"id": "exp-1",
"title": "Senior Engineer at Acme",
"start": "2020-01-01",
"end": "2023-12-31",
"tags": ["backend", "microservices"]
}
],
"settings": {
"tone": "professional",
"compression_ratio": 0.7
}
}
Response:
{
"narrative_blocks": [
{
"block_id": "nb-1",
"text": "Led the architecture and implementation of a microservices platform...",
"weight": 0.9,
"sources": ["exp-1"],
"meta": {
"personality": "analytical",
"setting": "professional"
}
}
]
}
GET /profiles/{profileId}/experiences
POST /profiles/{profileId}/experiences
Content-Type: application/json
Request Body:
{
"title": "Senior Software Engineer",
"company": "Acme Inc",
"location": "San Francisco, CA",
"startDate": "2020-01-01",
"endDate": "2023-12-31",
"isCurrent": false,
"description": "Led backend team...",
"achievements": [
"Reduced latency by 40%",
"Migrated to microservices"
],
"technologies": ["Node.js", "PostgreSQL", "Docker"],
"tags": ["backend", "leadership"]
}
PATCH /profiles/{profileId}/experiences/{id}
DELETE /profiles/{profileId}/experiences/{id}
GET /profiles/{profileId}/skills
POST /profiles/{profileId}/skills
Content-Type: application/json
Request Body:
{
"name": "TypeScript",
"category": "Programming Languages",
"proficiencyLevel": "expert",
"yearsOfExperience": 5,
"tags": ["frontend", "backend"]
}
GET /profiles/{profileId}/projects
POST /profiles/{profileId}/projects
Content-Type: application/json
Request Body:
{
"name": "Open Source CLI Tool",
"description": "A productivity tool for developers",
"url": "https://github.com/user/project",
"startDate": "2024-01-01",
"status": "active",
"technologies": ["TypeScript", "Node.js"],
"tags": ["open-source", "cli"]
}
GET /masks
Returns predefined identity masks from the taxonomy.
Query Parameters:
ontology (string, optional): Filter by ontology (cognitive/expressive/operational)Response:
{
"masks": [
{
"id": "analyst",
"name": "Analyst",
"ontology": "cognitive-precision",
"functional_scope": "Precision reasoning and structured analysis",
"stylistic_parameters": {
"tone": "formal",
"rhetorical_mode": "analytical",
"compression_ratio": 0.6
}
}
]
}
GET /masks/{id}
GET /epochs
Returns temporal epoch definitions (e.g., “Formative”, “Mature”, “Synthesis”).
GET /stages
Returns career stage definitions (e.g., “Learning”, “Contributing”, “Leading”).
GET /profiles/{id}/export/jsonld
Exports profile as semantic web JSON-LD.
Response:
{
"@context": "https://schema.org/",
"@type": "Person",
"name": "John Doe",
"jobTitle": "Software Engineer",
"worksFor": [...]
}
GET /profiles/{id}/export/pdf
Generates a formatted résumé PDF.
Query Parameters:
maskId (string, optional): Apply specific mask filterResponse: Binary PDF file
GET /profiles/{id}/export/vc
Exports W3C Verifiable Credential bundle.
Response:
{
"@context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiableCredential"],
"issuer": "did:example:123",
"issuanceDate": "2025-01-17T00:00:00Z",
"credentialSubject": {...}
}
The Hunter Protocol provides autonomous job search and application automation.
POST /jobs/search
Content-Type: application/json
Request Body:
{
"keywords": ["TypeScript", "Senior Engineer"],
"location": "Remote",
"profileId": "uuid"
}
Response:
{
"jobs": [
{
"id": "job-1",
"title": "Senior TypeScript Engineer",
"company": "Tech Corp",
"location": "Remote",
"salaryRange": "$150k-$200k",
"url": "https://example.com/job",
"postedAt": "2025-01-15T00:00:00Z"
}
]
}
POST /jobs/{jobId}/analyze-gap
Content-Type: application/json
Request Body:
{
"profileId": "uuid"
}
Response:
{
"required": ["TypeScript", "React", "PostgreSQL"],
"present": ["TypeScript", "React"],
"missing": ["PostgreSQL"],
"importance": "medium"
}
POST /jobs/{jobId}/tailor-resume
Content-Type: application/json
Request Body:
{
"profileId": "uuid"
}
Response:
{
"maskId": "architect",
"maskName": "Architect",
"highlightedExperiences": ["exp-1", "exp-2"],
"tailoringSummary": "Emphasized system design experience"
}
POST /jobs/{jobId}/generate-cover-letter
Content-Type: application/json
Request Body:
{
"profileId": "uuid",
"tone": "professional"
}
Response:
{
"text": "Dear Hiring Manager,\n\nI am excited to apply...",
"wordCount": 350
}
Access the unified GraphQL endpoint at /graphql.
GET /graphql/schema
query GetProfile($id: ID!) {
profile(id: $id) {
id
displayName
experiences {
title
company
startDate
}
masks {
name
ontology
}
}
}
subscription OnJobFound($profileId: ID!) {
jobFound(profileId: $profileId) {
id
title
company
}
}
All errors follow a consistent format:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request body",
"details": {
"field": "email",
"issue": "Invalid email format"
}
}
}
| Code | HTTP Status | Description |
|---|---|---|
VALIDATION_ERROR |
400 | Request validation failed |
UNAUTHORIZED |
401 | Missing or invalid authentication |
FORBIDDEN |
403 | Insufficient permissions |
NOT_FOUND |
404 | Resource not found |
CONFLICT |
409 | Resource already exists |
QUOTA_EXCEEDED |
429 | Rate limit or quota exceeded |
INTERNAL_ERROR |
500 | Server error |
| Feature | FREE | PRO | ENTERPRISE |
|---|---|---|---|
| Job Searches | 5/month | Unlimited | Unlimited |
| Resume Tailoring | 0/month | 5/month | Unlimited |
| Cover Letters | 0/month | 3/month | Unlimited |
| Auto-Apply | 0/month | 5/month | Unlimited |
Responses include rate limit information:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 75
X-RateLimit-Reset: 1642435200
When quota is exceeded, the API returns:
{
"error": {
"code": "QUOTA_EXCEEDED",
"message": "Monthly quota exceeded for this feature",
"details": {
"feature": "resume_tailoring",
"limit": 5,
"used": 5,
"resetDate": "2025-02-01T00:00:00Z"
}
}
}
API Response Times (p95, local dev):
Caching:
/openapi.yaml, /openapi-hunter.yaml/docs/redoc/graphql