FreeBoard

FreeBoard API

Every feature of the web app through the REST API (https://freeboard-rosy.vercel.app/api/v1) and MCP. API keys need a paid plan. OpenAPI JSON

Authentication, limits, errors

curl -H "x-api-key: $FREEBOARD_API_KEY" https://freeboard-rosy.vercel.app/api/v1/applications

MCP

Streamable HTTP at https://freeboard-rosy.vercel.app/api/mcp, with your API key (x-api-key or Authorization: Bearer). Tools: add_job_by_url, get_job_import, submit_job_fields, list_applications, get_application, update_application_status, add_application_note, list_tasks, create_task, complete_task.

claude mcp add --transport http freeboard https://freeboard-rosy.vercel.app/api/mcp --header "x-api-key: fb_..."
{
  "mcpServers": {
    "freeboard": {
      "type": "http",
      "url": "https://freeboard-rosy.vercel.app/api/mcp",
      "headers": {
        "Authorization": "Bearer ${FREEBOARD_API_KEY}"
      }
    }
  }
}

.mcp.json is usually committed: never put a real key in it. Claude Code fills in ${FREEBOARD_API_KEY} from your environment.

Tool results contain text from job pages anyone can write, and it can carry instructions aimed at your AI assistant. Such text could try to drive the write tools (status changes, notes, tasks): approve each write call in your client instead of allowing them automatically.

Account

GET /me

Current user, how you authenticated, and your plan

GET /ai/status

Which AI features this server and your plan have

Applications

GET /applications

List applications, newest first

Query
NameSchema
q{"type":"string","maxLength":200}
status{"type":"string","enum":["SAVED","APPLIED","SCREENING","TECHNICAL_INTERVIEW","TAKE_HOME","FINAL_INTERVIEW","OFFER","REJECTED","WITHDRAWN"]}
archived{"type":"string"}
limit{"default":25,"type":"integer","minimum":1,"maximum":100}
offset{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}

POST /applications

Create an application

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "company": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "roleTitle": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "location": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "workMode": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "REMOTE",
            "HYBRID",
            "ONSITE"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "jobUrl": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 2000
        },
        {
          "type": "null"
        }
      ]
    },
    "jobDescription": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 50000
        },
        {
          "type": "null"
        }
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "SAVED",
        "APPLIED",
        "SCREENING",
        "TECHNICAL_INTERVIEW",
        "TAKE_HOME",
        "FINAL_INTERVIEW",
        "OFFER",
        "REJECTED",
        "WITHDRAWN"
      ]
    },
    "priority": {
      "type": "string",
      "enum": [
        "LOW",
        "MEDIUM",
        "HIGH"
      ]
    },
    "salaryMin": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000000
        },
        {
          "type": "null"
        }
      ]
    },
    "salaryMax": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000000
        },
        {
          "type": "null"
        }
      ]
    },
    "salaryCurrency": {
      "anyOf": [
        {
          "type": "string",
          "pattern": "^[A-Z]{3}$"
        },
        {
          "type": "null"
        }
      ]
    },
    "source": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "nextStep": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ]
    },
    "notesSummary": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 2000
        },
        {
          "type": "null"
        }
      ]
    },
    "appliedAt": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "primaryContactName": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "initialNotes": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 5000
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "company",
    "roleTitle"
  ],
  "additionalProperties": false
}

GET /applications/duplicates

Find possible duplicates by job URL or company + role

Query
NameSchema
company{"type":"string","maxLength":100}
roleTitle{"type":"string","maxLength":100}
jobUrl{"type":"string","maxLength":2000}

GET /applications/{id}

One application with its summary and extraction method

PATCH /applications/{id}

Change an application (archive/restore with archived)

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "company": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "roleTitle": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "location": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "workMode": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "REMOTE",
            "HYBRID",
            "ONSITE"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "jobUrl": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 2000
        },
        {
          "type": "null"
        }
      ]
    },
    "jobDescription": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 50000
        },
        {
          "type": "null"
        }
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "SAVED",
        "APPLIED",
        "SCREENING",
        "TECHNICAL_INTERVIEW",
        "TAKE_HOME",
        "FINAL_INTERVIEW",
        "OFFER",
        "REJECTED",
        "WITHDRAWN"
      ]
    },
    "priority": {
      "type": "string",
      "enum": [
        "LOW",
        "MEDIUM",
        "HIGH"
      ]
    },
    "salaryMin": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000000
        },
        {
          "type": "null"
        }
      ]
    },
    "salaryMax": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000000
        },
        {
          "type": "null"
        }
      ]
    },
    "salaryCurrency": {
      "anyOf": [
        {
          "type": "string",
          "pattern": "^[A-Z]{3}$"
        },
        {
          "type": "null"
        }
      ]
    },
    "source": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "nextStep": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ]
    },
    "notesSummary": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 2000
        },
        {
          "type": "null"
        }
      ]
    },
    "appliedAt": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "archived": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}

DELETE /applications/{id}

Delete an application

POST /applications/{id}/duplicate

Copy an application

Interviews

GET /applications/{id}/interviews

Interviews of an application

POST /applications/{id}/interviews

Add an interview

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "RECRUITER",
        "TECHNICAL",
        "BEHAVIORAL",
        "MANAGER",
        "PANEL",
        "TAKE_HOME_REVIEW",
        "FINAL",
        "OTHER"
      ]
    },
    "stageName": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "scheduledAt": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "durationMinutes": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 1440
        },
        {
          "type": "null"
        }
      ]
    },
    "interviewerName": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "interviewerRole": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "locationOrLink": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 500
        },
        {
          "type": "null"
        }
      ]
    },
    "outcome": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "PENDING",
            "PASSED",
            "FAILED",
            "CANCELLED"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "notes": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 5000
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "type",
    "stageName"
  ],
  "additionalProperties": false
}

PATCH /interviews/{id}

Change an interview

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "RECRUITER",
        "TECHNICAL",
        "BEHAVIORAL",
        "MANAGER",
        "PANEL",
        "TAKE_HOME_REVIEW",
        "FINAL",
        "OTHER"
      ]
    },
    "stageName": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "scheduledAt": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "durationMinutes": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 1440
        },
        {
          "type": "null"
        }
      ]
    },
    "interviewerName": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "interviewerRole": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "locationOrLink": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 500
        },
        {
          "type": "null"
        }
      ]
    },
    "outcome": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "PENDING",
            "PASSED",
            "FAILED",
            "CANCELLED"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "notes": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 5000
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "additionalProperties": false
}

DELETE /interviews/{id}

Delete an interview

Notes

GET /applications/{id}/notes

Notes of an application

POST /applications/{id}/notes

Add a note

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "title": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "content": {
      "type": "string",
      "minLength": 1,
      "maxLength": 5000
    },
    "assessmentDelivered": {
      "type": "boolean"
    }
  },
  "required": [
    "content"
  ],
  "additionalProperties": false
}

GET /notes/{id}

One note

PATCH /notes/{id}

Change a note

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "title": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "content": {
      "type": "string",
      "minLength": 1,
      "maxLength": 5000
    },
    "assessmentDelivered": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}

DELETE /notes/{id}

Delete a note

Tasks

GET /tasks

List tasks

Query
NameSchema
q{"type":"string","maxLength":200}
status{"default":"open","type":"string","enum":["open","completed","all"]}
applicationId{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}
limit{"default":25,"type":"integer","minimum":1,"maximum":100}
offset{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}

POST /tasks

Create a task

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 150
    },
    "description": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 2000
        },
        {
          "type": "null"
        }
      ]
    },
    "dueAt": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "applicationId": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "title"
  ],
  "additionalProperties": false
}

GET /tasks/{id}

One task

PATCH /tasks/{id}

Change a task (complete with completed)

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 150
    },
    "description": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 2000
        },
        {
          "type": "null"
        }
      ]
    },
    "dueAt": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "applicationId": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    },
    "completed": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}

DELETE /tasks/{id}

Delete a task

POST /tasks/{id}/duplicate

Copy a task

Contacts

GET /contacts

List contacts

Query
NameSchema
q{"type":"string","maxLength":200}
limit{"default":25,"type":"integer","minimum":1,"maximum":100}
offset{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}

POST /contacts

Create a contact

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "fullName": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "email": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 255
        },
        {
          "type": "null"
        }
      ]
    },
    "phone": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 50
        },
        {
          "type": "null"
        }
      ]
    },
    "linkedinUrl": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 500
        },
        {
          "type": "null"
        }
      ]
    },
    "company": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "jobTitle": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "notes": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 5000
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "fullName"
  ],
  "additionalProperties": false
}

GET /contacts/{id}

One contact with follow-up count and links

PATCH /contacts/{id}

Change a contact

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "fullName": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "email": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 255
        },
        {
          "type": "null"
        }
      ]
    },
    "phone": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 50
        },
        {
          "type": "null"
        }
      ]
    },
    "linkedinUrl": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 500
        },
        {
          "type": "null"
        }
      ]
    },
    "company": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "jobTitle": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "notes": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 5000
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "additionalProperties": false
}

DELETE /contacts/{id}

Delete a contact (unlinks its follow-ups)

POST /contacts/{id}/duplicate

Copy a contact

GET /applications/{id}/contacts

Contacts linked to an application

POST /applications/{id}/contacts

Link a contact to an application in a role

Request body (JSON Schema)
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "contactId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "role": {
          "type": "string",
          "enum": [
            "RECRUITER",
            "HIRING_MANAGER",
            "INTERVIEWER",
            "REFERRAL",
            "COORDINATOR",
            "OTHER"
          ]
        }
      },
      "required": [
        "contactId"
      ],
      "additionalProperties": false
    },
    {
      "type": "object",
      "properties": {
        "contact": {
          "type": "object",
          "properties": {
            "fullName": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "email": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 255
                },
                {
                  "type": "null"
                }
              ]
            },
            "phone": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 50
                },
                {
                  "type": "null"
                }
              ]
            },
            "linkedinUrl": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 500
                },
                {
                  "type": "null"
                }
              ]
            },
            "company": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 100
                },
                {
                  "type": "null"
                }
              ]
            },
            "jobTitle": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 100
                },
                {
                  "type": "null"
                }
              ]
            },
            "notes": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 5000
                },
                {
                  "type": "null"
                }
              ]
            }
          },
          "required": [
            "fullName"
          ],
          "additionalProperties": false
        },
        "role": {
          "type": "string",
          "enum": [
            "RECRUITER",
            "HIRING_MANAGER",
            "INTERVIEWER",
            "REFERRAL",
            "COORDINATOR",
            "OTHER"
          ]
        }
      },
      "required": [
        "contact"
      ],
      "additionalProperties": false
    }
  ]
}

PATCH /application-contacts/{id}

Change a contact link

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "role": {
      "type": "string",
      "enum": [
        "RECRUITER",
        "HIRING_MANAGER",
        "INTERVIEWER",
        "REFERRAL",
        "COORDINATOR",
        "OTHER"
      ]
    }
  },
  "required": [
    "role"
  ],
  "additionalProperties": false
}

DELETE /application-contacts/{id}

Remove a contact link

Follow-ups

GET /follow-ups

List follow-ups

Query
NameSchema
q{"type":"string","maxLength":200}
status{"default":"PLANNED","type":"string","enum":["PLANNED","DONE","MISSED","archived","all"]}
contactId{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}
applicationId{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}
limit{"default":25,"type":"integer","minimum":1,"maximum":100}
offset{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}

POST /follow-ups

Create a follow-up

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 150
    },
    "description": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 120
        },
        {
          "type": "null"
        }
      ]
    },
    "notes": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 2000
        },
        {
          "type": "null"
        }
      ]
    },
    "scheduledAt": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "PLANNED",
        "DONE",
        "MISSED"
      ]
    },
    "contactId": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    },
    "applicationId": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "title"
  ],
  "additionalProperties": false
}

GET /follow-ups/{id}

One follow-up

PATCH /follow-ups/{id}

Change a follow-up (status DONE/MISSED archives it)

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 150
    },
    "description": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 120
        },
        {
          "type": "null"
        }
      ]
    },
    "notes": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 2000
        },
        {
          "type": "null"
        }
      ]
    },
    "scheduledAt": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "PLANNED",
        "DONE",
        "MISSED"
      ]
    },
    "contactId": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    },
    "applicationId": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "additionalProperties": false
}

DELETE /follow-ups/{id}

Delete a follow-up

POST /follow-ups/{id}/duplicate

Copy a follow-up

Dashboard

GET /dashboard/summary

Stats, open and overdue work, needs attention

GET /activity

Recent activity, newest first

Query
NameSchema
type{"type":"string","enum":["applications","tasks","followUps","interviews","notes","contacts"]}
applicationId{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}
limit{"default":12,"type":"integer","minimum":1,"maximum":50}

Settings

GET /preferences

Dashboard and model preferences

PATCH /preferences

Change preferences

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "hiddenDashboardSections": {
      "maxItems": 12,
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "utilities",
          "applications",
          "tasks",
          "followUps",
          "contacts",
          "timeline"
        ]
      }
    },
    "aiModelPreset": {
      "type": "string",
      "enum": [
        "BALANCED",
        "QUALITY",
        "ECONOMY"
      ]
    }
  },
  "additionalProperties": false
}

PUT /settings/anthropic-key

Save your own Anthropic API key (validated, sealed)

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "apiKey": {
      "type": "string",
      "minLength": 20,
      "maxLength": 300,
      "pattern": "^[\\x21-\\x7e]+$"
    }
  },
  "required": [
    "apiKey"
  ],
  "additionalProperties": false
}

DELETE /settings/anthropic-key

Remove your Anthropic API key

Profile

GET /profile

Master resume and job preferences

PATCH /profile/preferences

Change job preferences and weights

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "workModes": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "REMOTE",
          "HYBRID",
          "ONSITE"
        ]
      }
    },
    "locations": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 100
      }
    },
    "needsVisaSponsorship": {
      "type": "boolean"
    },
    "hasSecurityClearance": {
      "type": "boolean"
    },
    "citizenships": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 60
      }
    },
    "salaryFloor": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "amount": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100000000
            },
            "currency": {
              "type": "string",
              "pattern": "^[A-Z]{3}$"
            }
          },
          "required": [
            "amount",
            "currency"
          ],
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ]
    },
    "seniority": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "JUNIOR",
            "MID",
            "SENIOR",
            "STAFF",
            "PRINCIPAL"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "roleTypes": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "FRONTEND",
          "BACKEND",
          "FULLSTACK",
          "INFRA",
          "ML"
        ]
      }
    },
    "stack": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 50
      }
    },
    "domains": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 60
      }
    },
    "weights": {
      "type": "object",
      "properties": {
        "stack": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10
        },
        "seniority": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10
        },
        "roleType": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10
        },
        "domain": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10
        }
      },
      "required": [
        "stack",
        "seniority",
        "roleType",
        "domain"
      ],
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}

PUT /profile/resume

Replace the master resume

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "name": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "headline": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ]
    },
    "contact": {
      "type": "object",
      "properties": {
        "email": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 255
            },
            {
              "type": "null"
            }
          ]
        },
        "phone": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 50
            },
            {
              "type": "null"
            }
          ]
        },
        "location": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 100
            },
            {
              "type": "null"
            }
          ]
        },
        "links": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300,
            "pattern": "^\\S*$"
          }
        }
      },
      "additionalProperties": false
    },
    "sections": {
      "minItems": 1,
      "maxItems": 30,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^s_[a-z0-9]{8}$"
          },
          "kind": {
            "type": "string",
            "enum": [
              "summary",
              "experience",
              "projects",
              "education",
              "skills",
              "other"
            ]
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "subtitle": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ]
          },
          "bullets": {
            "maxItems": 60,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "pattern": "^b_[a-z0-9]{8}$"
                },
                "text": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 500
                }
              },
              "required": [
                "text"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "kind",
          "title",
          "bullets"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "sections"
  ],
  "additionalProperties": false
}

DELETE /profile/resume

Delete the master resume

POST /profile/resume/draft

Structure a resume with Claude (Unverified AI draft; nothing stored)

Request body (JSON Schema)
{
  "type": "object",
  "required": [
    "text"
  ],
  "properties": {
    "text": {
      "type": "string",
      "minLength": 1,
      "maxLength": 30000
    }
  },
  "additionalProperties": false
}

GET /profile/resume/pdf

Master resume as an ATS PDF

Query
NameSchema
paper{"default":"a4","type":"string","enum":["a4","letter"]}

Job imports

POST /job-imports

Import a job from its link or pasted text (runs in the background)

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "maxLength": 2000,
      "format": "uri"
    },
    "text": {
      "type": "string"
    }
  },
  "additionalProperties": false
}

GET /job-imports/{id}

One import: status, what it waits for, the application it created

POST /job-imports/{id}/text

Paste the posting for an import waiting on TEXT

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "text": {
      "type": "string"
    }
  },
  "required": [
    "text"
  ],
  "additionalProperties": false
}

POST /job-imports/{id}/confirm

Confirm the basic draft of an import waiting on CONFIRM

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "company": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "roleTitle": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "location": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ]
    },
    "workMode": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "REMOTE",
            "HYBRID",
            "ONSITE"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "salaryMin": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000000
        },
        {
          "type": "null"
        }
      ]
    },
    "salaryMax": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000000
        },
        {
          "type": "null"
        }
      ]
    },
    "salaryCurrency": {
      "anyOf": [
        {
          "type": "string",
          "pattern": "^[A-Z]{3}$"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "company",
    "roleTitle"
  ],
  "additionalProperties": false
}

POST /job-imports/{id}/decision

Continue or skip an import waiting on DUPLICATE or FIT_DECISION

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "action": {
      "type": "string",
      "enum": [
        "continue",
        "skip"
      ]
    }
  },
  "required": [
    "action"
  ],
  "additionalProperties": false
}

POST /job-imports/{id}/retry

Retry a failed or stalled import

GET /job-imports/{id}/brief

What to extract, for your own model, from an import waiting on TEXT or CONFIRM

POST /job-imports/{id}/submit

Send the fields your own model extracted (marked Extracted by AI)

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "company": {
      "type": "string",
      "maxLength": 1000
    },
    "roleTitle": {
      "type": "string",
      "maxLength": 1000
    },
    "jobDescription": {
      "type": "string",
      "maxLength": 60000
    },
    "location": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 1000
        },
        {
          "type": "null"
        }
      ]
    },
    "workMode": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "REMOTE",
            "HYBRID",
            "ONSITE"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "salaryMin": {
      "type": [
        "number",
        "null"
      ]
    },
    "salaryMax": {
      "type": [
        "number",
        "null"
      ]
    },
    "salaryCurrency": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 10
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "company",
    "roleTitle",
    "jobDescription"
  ],
  "additionalProperties": false
}

Fit

GET /applications/{id}/fit

The stored Jev fit check

POST /applications/{id}/fit

Run the Jev fit check Paid plans only.

Documents

GET /applications/{id}/documents

Tailored resume, cover letter and answers of an application

POST /applications/{id}/tailored-resume

Tailor the master resume for this job (Claude, checked by Jev) Paid plans only.

POST /applications/{id}/cover-letter

Write a cover letter (Claude)

POST /applications/{id}/answers

Answer an application question (Claude)

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "question": {
      "type": "string",
      "minLength": 1,
      "maxLength": 1000
    }
  },
  "required": [
    "question"
  ],
  "additionalProperties": false
}

GET /documents/{id}

One AI document

PATCH /documents/{id}

Edit, remove, keep or add back lines; approve

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "lines": {
      "minItems": 1,
      "maxItems": 60,
      "type": "array",
      "items": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^c_[a-z0-9]{8}$"
              },
              "text": {
                "type": "string",
                "minLength": 1,
                "maxLength": 600
              }
            },
            "required": [
              "id",
              "text"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^c_[a-z0-9]{8}$"
              },
              "remove": {
                "type": "boolean",
                "const": true
              }
            },
            "required": [
              "id",
              "remove"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^c_[a-z0-9]{8}$"
              },
              "keep": {
                "type": "boolean",
                "const": true
              }
            },
            "required": [
              "id",
              "keep"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "addSourceId": {
                "type": "string",
                "pattern": "^b_[a-z0-9]{8}$"
              }
            },
            "required": [
              "addSourceId"
            ],
            "additionalProperties": false
          }
        ]
      }
    },
    "approved": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}

DELETE /documents/{id}

Delete an AI document

POST /documents/{id}/verify

Re-check the document's AI lines with Jev Paid plans only.

GET /documents/{id}/pdf

Approved tailored resume as an ATS PDF

Query
NameSchema
paper{"default":"a4","type":"string","enum":["a4","letter"]}

Billing

GET /billing

Your plan, your subscription and whether this server takes payments

POST /billing/checkout

Start a checkout for a paid plan (returns the payment page URL) Signed-in website only (API keys and MCP get 403).

Request body (JSON Schema)
{
  "type": "object",
  "properties": {
    "plan": {
      "type": "string",
      "enum": [
        "MONTHLY",
        "QUARTERLY",
        "ANNUAL"
      ]
    }
  },
  "required": [
    "plan"
  ],
  "additionalProperties": false
}

POST /billing/portal

Open the payment provider's subscription portal (returns its URL) Signed-in website only (API keys and MCP get 403).