> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coffeechats.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Job tools

> Tools that read, search, add, import and edit your applications and postings, set stage and priority, and launch and track Chrome applies.

These tools read, search, add, import and edit your applications and postings, set stage and priority, and launch and track Chrome applies. They need the permissions `jobs:read` and `jobs:write`, which you grant on the Authorize access page when you connect.

This page is generated from the connector's tool catalogue. It describes 12 tools. Every tool reads or writes only your own account.

## Permissions this page needs

* `jobs:read`: Read your internship applications, the referral requests on them and individual job postings, search open job postings with the names of your contacts at each company, and read whether the Chrome extension is running and the status of your browser applications
* `jobs:write`: Add internship applications you plan to apply to or already applied to, edit their apply URL, notes and deadline, update their stage and priority, and queue a browser apply

The [permissions reference](https://docs.coffeechats.me/mcp/scopes.md) lists every permission you can grant.

## `jobs.applications.list`

Your agent host shows this tool as "List applications".

List the authenticated student's internship applications newest first with measured pagination.

Permissions: This tool needs `jobs:read`, which the Authorize access page describes as "Read your internship applications, the referral requests on them and individual job postings, search open job postings with the names of your contacts at each company, and read whether the Chrome extension is running and the status of your browser applications".

Risk: `read`. This tool only reads your own data. It never changes anything and it never asks for your approval.

### Input

| Property | Type | Required | Bounds |
| - | - | - | - |
| `cursor` | string | no | 1 to 512 characters; pattern `^[A-Za-z0-9_-]+$` |
| `includeArchived` | boolean | no | none stated |
| `limit` | integer | no | from 1 to 20 |
| `stage` | string | no | one of `SAVED`, `APPLIED`, `REFERRAL_RECEIVED`, `INTERVIEWING`, `OFFER`, `ACCEPTED`, `REJECTED`, `WITHDRAWN` |

### Example call

```json jobs.applications.list input theme={"system"}
{
  "limit": 10,
  "stage": "APPLIED"
}
```

### Result

A result is never larger than 16,384 bytes.
If the stored value does not fit, the tool returns a measured fragment and a cursor for the next one.

This tool's result takes one of these 2 forms, and one call returns exactly one of them. The field named beside each form below says which one you are looking at. Open a form to read its top-level fields.

> **Shape 1**
>
> ```json Top-level fields theme={"system"}
> [
>   "applications",
>   "nextCursor"
> ]
> ```

> **Shape 2**
>
> ```json Top-level fields theme={"system"}
> [
>   "applications",
>   "fragment",
>   "nextCursor"
> ]
> ```

### Errors

A failed call returns one protocol error with no error code, and its text is `Tool call failed.` every time. This tool looks up no record by id, so it never sends a text that names a record. The [error codes](https://docs.coffeechats.me/mcp/errors.md) page gives every text a read failure can carry.

## `jobs.applications.get`

Your agent host shows this tool as "Get application".

Read one internship application owned by the authenticated student.

Permissions: This tool needs `jobs:read`, which the Authorize access page describes as "Read your internship applications, the referral requests on them and individual job postings, search open job postings with the names of your contacts at each company, and read whether the Chrome extension is running and the status of your browser applications".

Risk: `read`. This tool only reads your own data. It never changes anything and it never asks for your approval.

### Input

| Property | Type | Required | Bounds |
| - | - | - | - |
| `cursor` | string | no | 1 to 512 characters; pattern `^[A-Za-z0-9_-]+$` |
| `id` | string | yes | pattern `^[a-f0-9]{24}$` |

### Example call

```json jobs.applications.get input theme={"system"}
{
  "id": "c0ffeec0ffeec0ffee000004"
}
```

### Result

A result is never larger than 16,384 bytes.
If the stored value does not fit, the tool returns a measured fragment and a cursor for the next one.

This tool's result takes one of these 2 forms, and one call returns exactly one of them. The field named beside each form below says which one you are looking at. Open a form to read its top-level fields.

> **Shape 1**
>
> ```json Top-level fields theme={"system"}
> [
>   "application"
> ]
> ```

> **Shape 2**
>
> ```json Top-level fields theme={"system"}
> [
>   "application",
>   "fragment",
>   "nextCursor"
> ]
> ```

### Errors

A failed call returns one protocol error with no error code. Its text is `Tool call failed.` in every case but one: a call that finds no application of yours says so and tells the agent to call the matching list tool. The [error codes](https://docs.coffeechats.me/mcp/errors.md) page quotes that text in full and lists the eight kinds of record it can name.

## `jobs.applications.referrals.list`

Your agent host shows this tool as "List application referrals".

List referral asks recorded on one owned application; SUBMITTED is student-recorded status, not proof of external submission.

Permissions: This tool needs `jobs:read`, which the Authorize access page describes as "Read your internship applications, the referral requests on them and individual job postings, search open job postings with the names of your contacts at each company, and read whether the Chrome extension is running and the status of your browser applications".

Risk: `read`. This tool only reads your own data. It never changes anything and it never asks for your approval.

### Input

| Property | Type | Required | Bounds |
| - | - | - | - |
| `cursor` | string | no | 1 to 512 characters; pattern `^[A-Za-z0-9_-]+$` |
| `id` | string | yes | pattern `^[a-f0-9]{24}$` |

### Example call

```json jobs.applications.referrals.list input theme={"system"}
{
  "id": "c0ffeec0ffeec0ffee000004"
}
```

### Result

A result is never larger than 16,384 bytes.

A result carries these top-level fields:

```json Top-level fields theme={"system"}
[
  "nextCursor",
  "referrals"
]
```

### Errors

A failed call returns one protocol error with no error code. Its text is `Tool call failed.` in every case but one: a call that finds no application of yours says so and tells the agent to call the matching list tool. The [error codes](https://docs.coffeechats.me/mcp/errors.md) page quotes that text in full and lists the eight kinds of record it can name.

## `jobs.postings.get`

Your agent host shows this tool as "Get job posting".

Read one posting from the shared catalogue available to every signed-in student; jobs.search finds posting ids.

Permissions: This tool needs `jobs:read`, which the Authorize access page describes as "Read your internship applications, the referral requests on them and individual job postings, search open job postings with the names of your contacts at each company, and read whether the Chrome extension is running and the status of your browser applications".

Risk: `read`. This tool only reads your own data. It never changes anything and it never asks for your approval.

### Input

| Property | Type | Required | Bounds |
| - | - | - | - |
| `cursor` | string | no | 1 to 512 characters; pattern `^[A-Za-z0-9_-]+$` |
| `id` | string | yes | pattern `^[a-f0-9]{24}$` |

### Example call

```json jobs.postings.get input theme={"system"}
{
  "id": "c0ffeec0ffeec0ffee000007"
}
```

### Result

A result is never larger than 16,384 bytes.
If the stored value does not fit, the tool returns a measured fragment and a cursor for the next one.

This tool's result takes one of these 2 forms, and one call returns exactly one of them. The field named beside each form below says which one you are looking at. Open a form to read its top-level fields.

> **Shape 1**
>
> ```json Top-level fields theme={"system"}
> [
>   "posting"
> ]
> ```

> **Shape 2**
>
> ```json Top-level fields theme={"system"}
> [
>   "fragment",
>   "nextCursor",
>   "posting"
> ]
> ```

### Errors

A failed call returns one protocol error with no error code. Its text is `Tool call failed.` in every case but one: a call that finds no posting of yours says so and tells the agent to call the matching list tool. The [error codes](https://docs.coffeechats.me/mcp/errors.md) page quotes that text in full and lists the eight kinds of record it can name.

Postings have no list tool. Find a posting id with `jobs.search`, or ask the student which posting to read.

## `jobs.search`

Your agent host shows this tool as "Search job postings".

Search open internship and job postings in the Coffee Chats jobs feed, optionally at up to 5 companies, returning at most limit rows (1-10, default 5). Each row has the posting id that jobs.postings.get reads and jobs.applications.create accepts as postingId, the company, title, location, salary, deadline, whether the student saved it, and the names of their contacts there. Postings are as last ingested; a search does not refresh them. truncated is true when rows were dropped to fit the page. About 10 searches a minute per connection; more return rate\_limited with retryAfterSeconds.

Permissions: This tool needs `jobs:read`, which the Authorize access page describes as "Read your internship applications, the referral requests on them and individual job postings, search open job postings with the names of your contacts at each company, and read whether the Chrome extension is running and the status of your browser applications".

Risk: `read`. This tool only reads your own data. It never changes anything and it never asks for your approval.

### Input

| Property | Type | Required | Bounds |
| - | - | - | - |
| `companies` | array | no | at most 5 items |
| `limit` | integer | no | from 1 to 10 |
| `query` | string | no | at most 200 characters |

### Example call

```json jobs.search input theme={"system"}
{
  "companies": [
    "Stripe"
  ],
  "limit": 5,
  "query": "software engineering intern"
}
```

### Result

A result is never larger than 16,384 bytes.

This tool's result takes one of these 2 forms, and one call returns exactly one of them. The field named beside each form below says which one you are looking at. Open a form to read its top-level fields.

> **Shape 1**
>
> ```json Top-level fields theme={"system"}
> [
>   "jobs",
>   "truncated"
> ]
> ```

> **Shape 2**
>
> ```json Top-level fields theme={"system"}
> [
>   "error",
>   "retryAfterSeconds"
> ]
> ```

### Errors

A failed call returns one protocol error with no error code, and its text is `Tool call failed.` every time. This tool looks up no record by id, so it never sends a text that names a record. The [error codes](https://docs.coffeechats.me/mcp/errors.md) page gives every text a read failure can carry.

## `jobs.apply_batches.list`

Your agent host shows this tool as "List apply batches".

Read the student's browser apply status: whether the Coffee Chats Chrome extension is running (with its install link), the jobs on their Applying list, and the latest 5 application batches with counts and each job's company, role, mode, status and reason (the oldest batches may show counts only). Launch with jobs.applications.apply. To record a job the student applied to elsewhere, use jobs.applications.create with stage APPLIED.

Permissions: This tool needs `jobs:read`, which the Authorize access page describes as "Read your internship applications, the referral requests on them and individual job postings, search open job postings with the names of your contacts at each company, and read whether the Chrome extension is running and the status of your browser applications".

Risk: `read`. This tool only reads your own data. It never changes anything and it never asks for your approval.

### Input

This tool takes no input.

### Example call

```json jobs.apply_batches.list input theme={"system"}
{}
```

### Result

A result is never larger than 65,536 bytes.

A result carries these top-level fields:

```json Top-level fields theme={"system"}
[
  "applying",
  "applyingUrl",
  "batches",
  "extension",
  "jobCredits",
  "note"
]
```

### Errors

A failed call returns one protocol error with no error code, and its text is `Tool call failed.` every time. This tool looks up no record by id, so it never sends a text that names a record. The [error codes](https://docs.coffeechats.me/mcp/errors.md) page gives every text a read failure can carry.

## `jobs.applications.stage.update`

Your agent host shows this tool as "Update application stage".

What this changes: Move one internship application to a stage and a priority.

Both are written together and both are required, so send the value you want to keep as well as the one you are changing; read them first with jobs.applications.get. The stage is one of SAVED, APPLIED, REFERRAL\_RECEIVED, INTERVIEWING, OFFER, ACCEPTED, REJECTED or WITHDRAWN and the priority one of HIGH, MEDIUM or LOW; neither can be cleared. Moving off SAVED for the first time records the applied date, exactly as the app does. Nothing else on the application is changed and nobody is contacted.

Permissions: This tool needs `jobs:write`, which the Authorize access page describes as "Add internship applications you plan to apply to or already applied to, edit their apply URL, notes and deadline, update their stage and priority, and queue a browser apply".

Risk: `safe_write`. This tool changes one of your own settings as soon as the agent calls it. It does not ask you to approve first, because the change affects only your own account and you can set it back yourself.

### Input

| Property | Type | Required | Bounds |
| - | - | - | - |
| `applicationId` | string | yes | pattern `^[a-f0-9]{24}$` |
| `idempotencyKey` | string | yes | 16 to 128 characters |
| `priority` | string | yes | one of `HIGH`, `MEDIUM`, `LOW` |
| `stage` | string | yes | one of `SAVED`, `APPLIED`, `REFERRAL_RECEIVED`, `INTERVIEWING`, `OFFER`, `ACCEPTED`, `REJECTED`, `WITHDRAWN` |

### Example call

```json jobs.applications.stage.update input theme={"system"}
{
  "applicationId": "c0ffeec0ffeec0ffee000004",
  "idempotencyKey": "example-idempotency-key-0012",
  "priority": "HIGH",
  "stage": "APPLIED"
}
```

### Result

A result is never larger than 4,096 bytes.

This tool's result takes one of these 4 forms, and one call returns exactly one of them. The field named beside each form below says which one you are looking at. Open a form to read its top-level fields.

> **Shape 1, where tag is completed**
>
> ```json Top-level fields theme={"system"}
> [
>   "operationId",
>   "operationStatus",
>   "result",
>   "scenario",
>   "tag"
> ]
> ```

> **Shape 2, where tag is accepted**
>
> ```json Top-level fields theme={"system"}
> [
>   "operationId",
>   "operationStatus",
>   "scenario",
>   "tag"
> ]
> ```

> **Shape 3, where status is failed**
>
> ```json Top-level fields theme={"system"}
> [
>   "error",
>   "operationId",
>   "scenario",
>   "status"
> ]
> ```

> **Shape 4, where status is uncertain**
>
> ```json Top-level fields theme={"system"}
> [
>   "error",
>   "operationId",
>   "scenario",
>   "status"
> ]
> ```

### The result may carry a retry hint

A call can be accepted and still ask the agent to come back later. When that happens the result is an accepted result and not a failure, and it carries a hint beside it holding one of these codes and a delay in milliseconds. Nothing has gone wrong and nothing has been written yet.

| Code | What it means |
| - | - |
| `PERMIT_BACKPRESSURE` | Too much work is already running on this connection. The agent should wait for the stated delay and call the tool again. |
| `PERMIT_CONTENTION` | Another call was holding the same slot. The agent should wait for the stated delay and call the tool again. |

### Errors

A call that does not succeed carries one of these codes.

| Code | What it means |
| - | - |
| `ACTION_DENIED` | Coffee Chats would not let this connection make the change, so nothing was written. The connection may have been revoked, or it may no longer hold the permission this tool needs. |
| `ACTION_EXPIRED` | Coffee Chats did not finish the change inside the short window it allows itself, and stopped rather than write late. Nothing was written. Ask the agent to make the change again. |
| `NOT_APPLIED` | Coffee Chats stopped before writing anything. Your data is exactly as it was. |
| `OUTCOME_UNKNOWN` | Coffee Chats cannot prove whether the change was written and will not guess. Open your Coffee Chats page and look before you decide what to do. Do not ask the agent to retry with a new key, because that could apply the change twice. |
| `SERVICE_UNAVAILABLE` | Coffee Chats could not do the work just now and wrote nothing. Try again later. |
| `VERSION_CONFLICT` | Your stored preference changed after the agent read it, so nothing was written. Ask the agent to read it again and make the change from what is there now. |

## `jobs.applications.create`

Your agent host shows this tool as "Add application".

What this changes: Add an internship or job application to the student's tracker: stage SAVED (planning to apply, the default) or APPLIED (already applied, which records the applied date).

Send a postingId from jobs.search, which fills the company, role, location, apply URL and deadline, or a companyName, role and http(s) applicationUrl; exactly one of postingId or applicationUrl. Optional priority (HIGH, MEDIUM or LOW), notes, location and deadlineAt. A row that already exists for the same posting, or with the same company, role and apply URL, is returned with duplicate: true instead of adding another; asking for APPLIED moves a SAVED one to APPLIED. extensionReady says whether jobs.applications.apply can queue the row for the Chrome extension now; when it cannot, extensionBlockers says why. An apply URL you typed must be approved by the student in the extension side panel first. Once the student has added 1000 applications in the last hour, this returns rate\_limited and adds nothing.

Permissions: This tool needs `jobs:write`, which the Authorize access page describes as "Add internship applications you plan to apply to or already applied to, edit their apply URL, notes and deadline, update their stage and priority, and queue a browser apply".

Risk: `safe_write`. This tool changes one of your own settings as soon as the agent calls it. It does not ask you to approve first, because the change affects only your own account and you can set it back yourself.

### Input

The agent sends one object, and the table below is that object exactly as the connector publishes it. The connector accepts the object in one of these 2 forms and refuses any mixture of them. A published schema cannot state that rule, which is why the Required column reads `no` on every property and why each form is written out under the table. Within a form, every property the form does not name is refused.

| Property | Type | Required | Bounds |
| - | - | - | - |
| `applicationUrl` | string | no | at most 2048 characters; pattern `^https?:\/\/\S+$` |
| `companyName` | string | no | 1 to 200 characters |
| `deadlineAt` | string or string | no | format `date`; format `date-time` |
| `location` | string | no | at most 200 characters |
| `notes` | string | no | at most 4000 characters |
| `postingId` | string | no | pattern `^[a-f0-9]{24}$` |
| `priority` | string | no | one of `HIGH`, `MEDIUM`, `LOW` |
| `role` | string | no | 1 to 200 characters |
| `stage` | string | no | one of `SAVED`, `APPLIED` |

#### Form 1, sending `postingId`

Send `postingId`. It is required in this form. `companyName`, `deadlineAt`, `location`, `notes`, `priority`, `role` and `stage` may be sent beside it, and nothing else may be.

#### Form 2, sending `applicationUrl`, `companyName`, `role`

Send `applicationUrl`, `companyName` and `role`. They are required in this form. `deadlineAt`, `location`, `notes`, `priority` and `stage` may be sent beside them, and nothing else may be.

### Example calls

```json jobs.applications.create input form 1 theme={"system"}
{
  "postingId": "c0ffeec0ffeec0ffee000007",
  "priority": "HIGH",
  "stage": "SAVED"
}
```

```json jobs.applications.create input form 2 theme={"system"}
{
  "applicationUrl": "https://example.com/careers/software-intern",
  "companyName": "Example Labs",
  "role": "Software Engineering Intern",
  "stage": "APPLIED"
}
```

### Result

A result is never larger than 4,096 bytes.

This tool's result takes one of these 2 forms, and one call returns exactly one of them. The field named beside each form below says which one you are looking at. Open a form to read its top-level fields.

> **Shape 1**
>
> ```json Top-level fields theme={"system"}
> [
>   "applicationId",
>   "duplicate",
>   "extensionBlockers",
>   "extensionReady",
>   "stage"
> ]
> ```

> **Shape 2**
>
> ```json Top-level fields theme={"system"}
> [
>   "error",
>   "message"
> ]
> ```

### Errors

A call that does not succeed carries one of these codes.

| Code | What it means |
| - | - |
| `SERVICE_UNAVAILABLE` | Coffee Chats could not do the work just now and wrote nothing. Try again later. |

## `jobs.applications.update`

Your agent host shows this tool as "Edit application".

What this changes: Edit a tracked internship or job application: its http(s) applicationUrl, notes, deadlineAt (null clears it), location, role or companyName.

Only the fields you send change. notes replaces the whole notes text, including anything the student wrote, and the application tools return only its length (notesChars), so send notes only when the student asked you to replace them. The same text also replaces the notes on the student's other applications at the same company that still held the old text, as in the app. Stage and priority are not edited here: use jobs.applications.stage.update. extensionReady says whether jobs.applications.apply can queue the row for the Chrome extension now; when it cannot, extensionBlockers says why. An apply URL you set must be approved by the student in the extension side panel first. jobs\_onboarding\_required means the student has not finished job application setup.

Permissions: This tool needs `jobs:write`, which the Authorize access page describes as "Add internship applications you plan to apply to or already applied to, edit their apply URL, notes and deadline, update their stage and priority, and queue a browser apply".

Risk: `safe_write`. This tool changes one of your own settings as soon as the agent calls it. It does not ask you to approve first, because the change affects only your own account and you can set it back yourself.

### Input

| Property | Type | Required | Bounds |
| - | - | - | - |
| `applicationId` | string | yes | pattern `^[a-f0-9]{24}$` |
| `applicationUrl` | string | no | at most 2048 characters; pattern `^https?:\/\/\S+$` |
| `companyName` | string | no | 1 to 200 characters |
| `deadlineAt` | null or string or string | no | format `date`; format `date-time` |
| `location` | string | no | at most 200 characters |
| `notes` | string | no | at most 4000 characters |
| `role` | string | no | 1 to 200 characters |

### Example call

```json jobs.applications.update input theme={"system"}
{
  "applicationId": "c0ffeec0ffeec0ffee000004",
  "deadlineAt": "2026-11-15",
  "notes": "Ask the alum on the payments team for a referral."
}
```

### Result

A result is never larger than 4,096 bytes.

This tool's result takes one of these 2 forms, and one call returns exactly one of them. The field named beside each form below says which one you are looking at. Open a form to read its top-level fields.

> **Shape 1**
>
> ```json Top-level fields theme={"system"}
> [
>   "applicationId",
>   "extensionBlockers",
>   "extensionReady",
>   "stage"
> ]
> ```

> **Shape 2**
>
> ```json Top-level fields theme={"system"}
> [
>   "error",
>   "message"
> ]
> ```

### Errors

A call that does not succeed carries one of these codes.

| Code | What it means |
| - | - |
| `SERVICE_UNAVAILABLE` | Coffee Chats could not do the work just now and wrote nothing. Try again later. |

## `jobs.applications.import.check`

Your agent host shows this tool as "Check a jobs spreadsheet".

Check a spreadsheet before jobs.applications.import, writing nothing. Takes the same input, forceNew included. Send the sheet as CSV text or as headers and rows. Convert .xlsx files to CSV first. Send csv or headers with rows, not both; rows are arrays of cells in header order. The call must fit in 2 MB and hold at most 1000 rows; split a bigger sheet. Returns which column maps to which job field, the columns that will go into notes, and the created, updated, skipped and failed counts the import would report against the jobs tracked now, with the first 10 row errors. Counts are an estimate: notes are shared across jobs at the same company, so some updates may become skips. When the sheet cannot be imported as sent (no header it recognizes, no rows, more than 1000 rows), problem says what to fix and the counts are zero.

Permissions: This tool needs `jobs:read`, which the Authorize access page describes as "Read your internship applications, the referral requests on them and individual job postings, search open job postings with the names of your contacts at each company, and read whether the Chrome extension is running and the status of your browser applications".

Risk: `read`. This tool only reads your own data. It never changes anything and it never asks for your approval.

### Input

The agent sends one object, and the table below is that object exactly as the connector publishes it. The connector accepts the object in one of these 2 forms and refuses any mixture of them. A published schema cannot state that rule, which is why the Required column reads `no` on every property and why each form is written out under the table. Within a form, every property the form does not name is refused.

| Property | Type | Required | Bounds |
| - | - | - | - |
| `csv` | string | no | 1 to 1500000 characters |
| `forceNew` | boolean | no | none stated |
| `headers` | array | no | 1 to 50 items |
| `rows` | array | no | at least 1 items |

#### Form 1, sending `csv`

Send `csv`. It is required in this form. `forceNew` may be sent beside it, and nothing else may be.

#### Form 2, sending `headers`, `rows`

Send `headers` and `rows`. They are required in this form. `forceNew` may be sent beside them, and nothing else may be.

### Example calls

```json jobs.applications.import.check input form 1 theme={"system"}
{
  "csv": "Company Name,Job Title,Job URL,Status\nExample Labs,Software Engineering Intern,https://example.com/careers/software-intern,Applied"
}
```

```json jobs.applications.import.check input form 2 theme={"system"}
{
  "headers": [
    "Company",
    "Role",
    "Status"
  ],
  "rows": [
    [
      "Example Labs",
      "Software Engineering Intern",
      "Wishlist"
    ]
  ]
}
```

### Result

A result is never larger than 32,768 bytes.

A result carries these top-level fields:

```json Top-level fields theme={"system"}
[
  "columns",
  "created",
  "errors",
  "failed",
  "problem",
  "skipped",
  "total",
  "unmappedColumns",
  "updated"
]
```

### Errors

A failed call returns one protocol error with no error code, and its text is `Tool call failed.` every time. This tool looks up no record by id, so it never sends a text that names a record. The [error codes](https://docs.coffeechats.me/mcp/errors.md) page gives every text a read failure can carry.

## `jobs.applications.import`

Your agent host shows this tool as "Import jobs from a spreadsheet".

What this changes: Import a spreadsheet of jobs (Huntr, Teal, Simplify, Notion) into the student's tracker.

Send the sheet as CSV text or as headers and rows. Convert .xlsx files to CSV first. Send csv or headers with rows, not both; rows are arrays of cells in header order. The call must fit in 2 MB and hold at most 1000 rows; split a bigger sheet. Columns are found by name (Company, Role or Job Title, URL, Status, Deadline, Date Applied, Location, Notes); other columns go into notes as "column: value". Statuses map to stages (Wishlist is SAVED, Interview is INTERVIEWING, Ghosted is REJECTED); an unknown one is SAVED and kept in notes. A row matching a tracked job by apply URL, or by company and role, only fills its empty fields, so a repeated import adds nothing; forceNew adds a new job when the apply URLs differ. A row needs a company and a role. Rows past 1000 jobs added in the last hour fail. Returns counts and the first 10 row errors (row 1 is the first row under the header). Nothing is sent.

Permissions: This tool needs `jobs:write`, which the Authorize access page describes as "Add internship applications you plan to apply to or already applied to, edit their apply URL, notes and deadline, update their stage and priority, and queue a browser apply".

Risk: `safe_write`. This tool adds jobs to your tracker as soon as the agent calls it, and can fill an empty apply URL, location, deadline, applied date or notes on a job you already track. It does not ask you to approve first, because it changes only your own tracker, never replaces a value you typed or a stage, sends nothing, and you can delete what it added yourself.

### Input

The agent sends one object, and the table below is that object exactly as the connector publishes it. The connector accepts the object in one of these 2 forms and refuses any mixture of them. A published schema cannot state that rule, which is why the Required column reads `no` on every property and why each form is written out under the table. Within a form, every property the form does not name is refused.

| Property | Type | Required | Bounds |
| - | - | - | - |
| `csv` | string | no | 1 to 1500000 characters |
| `forceNew` | boolean | no | none stated |
| `headers` | array | no | 1 to 50 items |
| `rows` | array | no | at least 1 items |

#### Form 1, sending `csv`

Send `csv`. It is required in this form. `forceNew` may be sent beside it, and nothing else may be.

#### Form 2, sending `headers`, `rows`

Send `headers` and `rows`. They are required in this form. `forceNew` may be sent beside them, and nothing else may be.

### Example calls

```json jobs.applications.import input form 1 theme={"system"}
{
  "csv": "Company Name,Job Title,Job URL,Status\nExample Labs,Software Engineering Intern,https://example.com/careers/software-intern,Applied"
}
```

```json jobs.applications.import input form 2 theme={"system"}
{
  "forceNew": true,
  "headers": [
    "Company",
    "Role",
    "URL"
  ],
  "rows": [
    [
      "Example Labs",
      "Software Engineering Intern",
      "https://example.com/careers/software-intern-2"
    ]
  ]
}
```

### Result

A result is never larger than 32,768 bytes.

A result carries these top-level fields:

```json Top-level fields theme={"system"}
[
  "created",
  "errors",
  "failed",
  "skipped",
  "total",
  "updated"
]
```

### Errors

A row that cannot be added is counted in `failed` with its reason, and is not a failure of the call. A call Coffee Chats refuses before importing anything, such as a sheet with more than 1000 rows or with no company and role columns, writes nothing and returns an error whose text names what to fix. Otherwise a call that does not succeed carries this code.

| Code | What it means |
| - | - |
| `SERVICE_UNAVAILABLE` | Coffee Chats could not do the work just now and wrote nothing. Try again later. |

## `jobs.applications.apply`

Your agent host shows this tool as "Queue a browser apply".

What this changes: Launch saved internship applications for the Coffee Chats Chrome extension to fill in the student's browser.

The mode is capped by the student's setting: full\_access (fill and submit) only when they chose it in the app, autofill (fill and leave submit to the student) otherwise; omit mode to use their setting. When the extension is not running, nothing is filled or submitted: the jobs are added to Applications on the student's Jobs page and the result carries installUrl; installUrl is empty until the extension can be installed, so share a link only when the note gives one. A row whose apply URL an agent set stays blocked until the student approves it in the extension side panel or launches it from Applications. Read progress with jobs.apply\_batches.list. If job application setup is not finished, nothing is saved or filled and the note carries the setup link. The server never fills or submits a form.

Permissions: This tool needs `jobs:write`, which the Authorize access page describes as "Add internship applications you plan to apply to or already applied to, edit their apply URL, notes and deadline, update their stage and priority, and queue a browser apply".

Risk: `browser_handoff`. This tool starts work in the Coffee Chats extension running in your own browser as soon as the agent calls it, with no approval page. The connector fills and submits nothing itself. In Autofill the extension fills each form and stops before submit for you to press it on the page. In Full access, only if you turned it on in the app, the extension also submits. Nothing happens unless your browser is open and the extension is signed in.

### Input

| Property | Type | Required | Bounds |
| - | - | - | - |
| `internshipIds` | array | yes | 1 to 25 items |
| `mode` | string | no | one of `autofill`, `full_access` |

### Example call

```json jobs.applications.apply input theme={"system"}
{
  "internshipIds": [
    "0123456789abcdef01234567"
  ]
}
```

### Result

A result is never larger than 16,384 bytes.

A result carries these top-level fields:

```json Top-level fields theme={"system"}
[
  "added",
  "applyingUrl",
  "batchId",
  "blocked",
  "connected",
  "installUrl",
  "jobCreditDenial",
  "jobCredits",
  "mode",
  "note",
  "queued",
  "skipped"
]
```

### Errors

A call that does not succeed carries one of these codes.

| Code | What it means |
| - | - |
| `SERVICE_UNAVAILABLE` | Coffee Chats could not do the work just now and wrote nothing. Try again later. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.