← Back

Developer Documentation

Build with the Tamar API or use the CLI to tailor resumes from your terminal.

Getting Started

Base URL

https://ask-tamar.com/api/v1

Authentication

All API requests require a Bearer token in the Authorization header. API keys start with tmr_ and are 68 characters long.

Authorization: Bearer tmr_your_api_key_here

Getting an API Key

Sign in to your Tamar account, go to Profile β†’ API Keys, and create a new key. The raw key is shown once β€” store it securely. You can also create keys programmatically via the POST /v1/keys endpoint (authenticated with a session cookie).

Rate Limits

The Developer plan provides 60 requests per minute. Free accounts are limited to 5 requests per minute. Rate-limited responses include Retry-After, X-RateLimit-Limit, and X-RateLimit-Remaining headers.

Error Format

All errors return a consistent JSON structure:

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description"
  }
}
CodeMeaning
UNAUTHORIZEDMissing or invalid API key
BAD_REQUESTMalformed request or missing required fields
NOT_FOUNDResource does not exist or does not belong to you
LIMIT_REACHEDPlan generation or iteration limit hit (upgrade required)
RATE_LIMITEDToo many requests β€” slow down
UNPROCESSABLERequest was valid but could not be processed (e.g. unreadable file)
INTERNAL_ERRORServer error β€” try again later

Timeouts

Several endpoints involve AI processing and can take 15–60 seconds to respond. Set your HTTP client timeout to at least 120 seconds. Each endpoint below shows its typical response time.

Developer plan β€” $15/mo

Unlimited resumes, unlimited feedback iterations, and 60 API requests per minute. Built for teams and products integrating Tamar. Get started β†’

Endpoints

POST/v1/resumes/parse

Upload a PDF, DOCX, or TXT file and extract text content. Max 10 MB.

Request

Multipart form data with a file field.

curl -X POST https://ask-tamar.com/api/v1/resumes/parse \
  -H "Authorization: Bearer tmr_..." \
  -F "[email protected]"

Response 200

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "text": "John Doe\nSenior Software Engineer...",
    "fileName": "resume.pdf",
    "pages": 2
  }
}
StatusCodeDescription
400BAD_REQUESTNo file provided or unsupported format
401UNAUTHORIZEDMissing or invalid API key
422UNPROCESSABLECould not extract text from file
429RATE_LIMITEDRate limit exceeded
GET/v1/profiles

List all experience profiles for the authenticated user, most recently updated first.

Response 200

{
  "data": {
    "hasProfile": true,
    "profiles": [
      {
        "id": "660e8400-...",
        "name": "John Doe",
        "currentRole": "Senior Software Engineer",
        "seniority": "senior",
        "skills": ["Python", "AWS", "PostgreSQL"],
        "qaHistoryCount": 4,
        "sourceFileName": "resume.pdf",
        "updatedAt": "2026-03-28T10:00:00Z"
      }
    ]
  }
}

Returns hasProfile: false with an empty array if no profile exists yet.

StatusCodeDescription
401UNAUTHORIZEDMissing or invalid API key
429RATE_LIMITEDRate limit exceeded
POST/v1/profiles/questions

Generate tailored enrichment questions based on a resume. Use the returned questions to collect answers from the candidate, then pass them as qaHistory to POST /profiles/synthesize for a higher-quality experience profile.

Typical response time: 5–15s. Set your HTTP client timeout to at least 120s.

Two-step enrichment workflow

  1. Call POST /profiles/questions β†’ receive questions
  2. Present questions to the user, collect their answers
  3. Call POST /profiles/synthesize with qaHistory β†’ create enriched profile

Request

{
  "sourceResumeId": "550e8400-..."
}

Provide either sourceResumeId or resumeText.

Response 200

{
  "data": {
    "seniority": "senior",
    "questions": [
      "Can you tell me about a time you led a cross-functional project?",
      "What's the largest team or codebase you've owned end-to-end?"
    ]
  }
}
StatusCodeDescription
400BAD_REQUESTNo resume source provided
401UNAUTHORIZEDMissing or invalid API key
404NOT_FOUNDSource resume not found
429RATE_LIMITEDRate limit exceeded
POST/v1/profiles/synthesize

Create or update an enriched experience profile from resume text and optional Q&A history. Profiles enable higher-quality tailoring.

Typical response time: 15–45s. Set your HTTP client timeout to at least 120s.

Request

{
  "sourceResumeId": "550e8400-...",
  "resumeText": "John Doe\nSenior Software Engineer...",
  "qaHistory": [
    { "q": "Tell me about your leadership experience", "a": "I led a team of 5..." }
  ]
}

Provide either sourceResumeId or resumeText. The qaHistory is optional.

Response 200

{
  "data": {
    "profileId": "660e8400-...",
    "profileData": { "...": "structured experience profile" },
    "seniority": "senior"
  }
}
StatusCodeDescription
400BAD_REQUESTMissing resume text
401UNAUTHORIZEDMissing or invalid API key
404NOT_FOUNDSource resume not found
POST/v1/tailor

Generate a tailored resume by matching a resume or profile against a job description. Resolution order: profileId β†’ sourceResumeId β†’ resumeText.

Typical response time: 15–60s. Set your HTTP client timeout to at least 120s.

Request

{
  "profileId": "660e8400-...",
  "sourceResumeId": "550e8400-...",
  "resumeText": "John Doe\nSenior Software Engineer...",
  "jobDescription": "We are looking for a Senior Backend Engineer...",
  "jobUrl": "https://linkedin.com/jobs/12345"
}

Provide at least one of profileId, sourceResumeId, or resumeText. Provide either jobDescription or jobUrl.

cURL Example

curl -X POST https://ask-tamar.com/api/v1/tailor \
  -H "Authorization: Bearer tmr_..." \
  -H "Content-Type: application/json" \
  -d '{
    "sourceResumeId": "550e8400-...",
    "jobDescription": "Senior Backend Engineer at Acme Corp..."
  }'

Response 200

{
  "data": {
    "id": "770e8400-...",
    "quality": "enriched",
    "analysis": {
      "mustHaves": ["Python", "AWS", "PostgreSQL"],
      "niceToHaves": ["Kubernetes", "GraphQL"],
      "strongMatches": ["Python", "AWS"],
      "transferableSkills": ["System design β†’ architecture role"],
      "gaps": ["Kubernetes β€” no production experience listed"]
    },
    "resumeData": { "...": "structured resume data" },
    "changes": [{ "...": "list of changes made" }]
  }
}

The quality field is either enriched (used an experience profile) or basic (resume text only).

StatusCodeDescription
400BAD_REQUESTMissing required fields
401UNAUTHORIZEDMissing or invalid API key
402LIMIT_REACHEDResume generation limit reached
422UNPROCESSABLECould not fetch or parse jobUrl (site may block access β€” paste text instead)
429RATE_LIMITEDRate limit exceeded
GET/v1/tailor/:id

Fetch a generated resume by ID. Optionally specify a version number.

Query Parameters

ParamTypeDescription
versionintegerSpecific version number (optional)

Response 200

{
  "data": {
    "id": "770e8400-...",
    "resumeData": { "...": "structured resume" },
    "analysis": { "...": "match analysis" },
    "changes": [{ "...": "changes" }],
    "version": 2,
    "versions": [
      { "id": "770e8400-...", "version": 1, "feedback": null, "created_at": "2026-03-28T10:00:00Z" },
      { "id": "770e8400-...", "version": 2, "feedback": "Make the summary shorter", "created_at": "2026-03-28T10:05:00Z" }
    ],
    "quality": "enriched"
  }
}
StatusCodeDescription
401UNAUTHORIZEDMissing or invalid API key
404NOT_FOUNDResume not found
POST/v1/tailor/:id/feedback

Submit natural-language feedback to modify a generated resume. Creates a new version.

Typical response time: 10–30s. Set your HTTP client timeout to at least 120s.

Request

{
  "feedback": "Make the summary shorter and emphasize Python experience",
  "selectionContext": { "optional": "context about selected elements" }
}

Response 200

{
  "data": {
    "version": 3,
    "changes": [{ "...": "changes applied" }],
    "resumeData": { "...": "updated structured resume" }
  }
}
StatusCodeDescription
400BAD_REQUESTMissing feedback or resume is finalised
401UNAUTHORIZEDMissing or invalid API key
402LIMIT_REACHEDIteration limit reached
404NOT_FOUNDResume not found
GET/v1/tailor/:id/pdf

Generate and download a PDF of the tailored resume.

Typical response time: 3–10s. Set your HTTP client timeout to at least 120s.

cURL Example

curl -o resume.pdf \
  https://ask-tamar.com/api/v1/tailor/770e8400-.../pdf \
  -H "Authorization: Bearer tmr_..."

Response 200

Binary PDF file with Content-Type: application/pdf.

StatusCodeDescription
400BAD_REQUESTResume has no structured data yet
401UNAUTHORIZEDMissing or invalid API key
404NOT_FOUNDResume not found
GET/v1/account

Check your current plan, subscription status, and usage for the billing period.

Response 200

{
  "data": {
    "plan": "developer",
    "planLabel": "Developer",
    "subscriptionStatus": "active",
    "currentPeriodEnd": "2026-04-28T10:00:00Z",
    "canceling": false,
    "usage": {
      "resumesThisMonth": 7,
      "resumeLimit": null,
      "iterationsPerResume": null
    },
    "rateLimitPerMinute": 60
  }
}

resumeLimit and iterationsPerResume are null when unlimited.

StatusCodeDescription
401UNAUTHORIZEDMissing or invalid API key
429RATE_LIMITEDRate limit exceeded
POST/v1/keys

Create a new API key. Requires a session cookie (not an API key) β€” use this from the web app or after logging in. The raw key is returned once. Store it securely.

Request

{
  "name": "My integration"
}

Response 201

{
  "data": {
    "id": "880e8400-...",
    "key": "tmr_abc123def456...",
    "keyPrefix": "tmr_abc1...",
    "name": "My integration",
    "plan": "free",
    "createdAt": "2026-03-28T10:00:00Z"
  }
}

The key field is only shown in this response. Subsequent listings show only the prefix.

StatusCodeDescription
400BAD_REQUESTToo many keys or invalid name
401UNAUTHORIZEDSession required
GET/v1/keys

List your API keys. Requires a session cookie.

Response 200

{
  "data": [
    {
      "id": "880e8400-...",
      "keyPrefix": "tmr_abc1...",
      "name": "My integration",
      "plan": "free",
      "scopes": ["*"],
      "lastUsedAt": "2026-03-28T12:00:00Z",
      "expiresAt": null,
      "revoked": false,
      "createdAt": "2026-03-28T10:00:00Z"
    }
  ]
}
StatusCodeDescription
401UNAUTHORIZEDSession required
DELETE/v1/keys/:id

Revoke an API key. This is a soft-delete and cannot be undone. Requires a session cookie.

Response 200

{
  "data": {
    "id": "880e8400-...",
    "revoked": true
  }
}
StatusCodeDescription
401UNAUTHORIZEDSession required
404NOT_FOUNDKey not found or already revoked