---
name: job-studio-setup
description: Connect this agent to the user's Job Studio account with a personal API key, verify the connection, and add an opportunity to their queue. Use when the user asks to connect to Job Studio or hand it a job lead.
---

# Set up Job Studio

Job Studio (https://personaljobcopilot.xyz) helps one person run a job search: it scores résumé fit
against a job description, tailors applications, keeps a pipeline of
opportunities and prepares for interviews. The user does that work in the app.

An agent can do one thing today: **hand the user an opportunity**. It lands in
their queue at https://personaljobcopilot.xyz/opportunities, where they decide what to do with it.

Human page: https://personaljobcopilot.xyz/agents

## 1. Account and API key

- The user needs a Job Studio account. New users sign up at https://personaljobcopilot.xyz/signup;
  existing users sign in at https://personaljobcopilot.xyz/login.
- The user creates a key at https://personaljobcopilot.xyz/settings#api-keys (Settings → API keys). The key starts
  with `jc_` and is shown once.
- Ask the user to put the key in an environment variable, for example
  `JOB_STUDIO_API_KEY`. Do not ask them to paste the key, their password or any
  code into chat. Never print the key.
- A key acts as that user. Anyone with it can add rows to their queue. They can
  revoke it in Settings at any time.

No local tools are needed beyond an HTTP client such as `curl`.

## 2. Verify the connection (read, no changes)

```bash
curl -sS "https://personaljobcopilot.xyz/api/opportunities/inbound" \
  -H "X-API-Key: $JOB_STUDIO_API_KEY"
```

**Success check:** HTTP 200 and `"connected": true`. A `401` means the key is
missing, mistyped or revoked.

```json
{
  "connected": true,
  "endpoint": "/api/opportunities/inbound",
  "rateLimit": { "remaining": 100, "resetAt": "…" }
}
```

## 3. First action: add an opportunity (write)

Ask the user before this step. It adds a row to their real queue, and the API
cannot delete it. Use an opportunity the user named or approved.

```bash
curl -sS -X POST "https://personaljobcopilot.xyz/api/opportunities/inbound" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $JOB_STUDIO_API_KEY" \
  -H "Idempotency-Key: my-agent:northstar-head-of-product" \
  -d '{
    "who": { "name": "Jamie Chen", "title": "Talent Partner", "company": "Northstar" },
    "role": "Head of Product",
    "ask": "Open to a chat this week?",
    "why": "Matches my product leadership focus",
    "source": "linkedin-message",
    "agent": "my-agent"
  }'
```

**Success check:** HTTP 201 with `"created": true`, and the row is visible at
https://personaljobcopilot.xyz/opportunities. Sending the same request again returns HTTP 200 with
`"duplicate": true` and does not add a second row.

```json
{
  "success": true,
  "created": true,
  "duplicate": false,
  "incomplete": true,
  "savedJobId": "<uuid>",
  "company": "Northstar",
  "role": "Head of Product",
  "opportunitiesUrl": "/opportunities",
  "workspaceUrl": "/workspace?job=<uuid>"
}
```

### Payload

| Field | Required | Notes |
|-------|----------|-------|
| `who.name` | Yes | The person who reached out |
| `role` | Yes | Role or ask title |
| `why` | Yes | One line: why this is worth the user's time |
| `source` | Yes | linkedin-message, linkedin-notification, manual or other |
| `company` | Yes* | Top level or who.company |
| `who.title, who.contact` | No | Contact title; email or profile URL |
| `ask` | No | What they want, up to 8,000 characters |
| `url` | No | http(s) link to the post or thread |
| `description` | No | Full job description. Without it the row is saved as incomplete and is not scored |
| `rawText` | No | Original message text |
| `receivedAt` | No | ISO timestamp, defaults to now |
| `agent` | No | Your agent's name, shown as attribution |
| `idempotencyKey` | No | Or the Idempotency-Key header. 8–128 chars of letters, numbers, . _ : - |

\* `company` is required either at the top level or as `who.company`.

Errors: `401` bad or missing key, `400` invalid payload (with a `fields` list;
nothing is written), `429` rate limit, `500` server error. Retry with the same
Idempotency-Key.

## Available now

- Create and revoke personal API keys (jc_…) in Settings → API keys. A key is shown once and stored only as a hash.
- Check the connection: GET /api/opportunities/inbound with the X-API-Key header.
- Add one opportunity to the user's queue: POST /api/opportunities/inbound. It lands on /opportunities as a saved row with source and contact.
- Safe retries: the same Idempotency-Key (or the same payload) returns the existing row instead of a duplicate.
- Clear errors: missing key or a bad key returns 401; a bad payload returns 400 with a fields list and writes nothing.

## Not available

Nothing below is scheduled. Do not try to work around these.

- Reading, listing, editing or deleting opportunities through the API. The user reviews them in the app.
- Running fit scores, assessments, résumé tailoring or cover letters through the API. The user starts these in the app.
- Applying to jobs, sending messages or emails, or replying on LinkedIn. Job Studio never does these for an agent.
- Scraping LinkedIn or any other site.
- An MCP server or OAuth sign-in for agents. Use an API key.

## Rules for agents

- Only add opportunities the user asked for or approved.
- Keep `why` honest and short. Do not invent a job description; leave it out
  and the row stays unscored until the user adds one.
- Never apply, send, or reply on the user's behalf.
- Report what you added with the `workspaceUrl` from the response, prefixed
  with https://personaljobcopilot.xyz.
