# Bordfeed auth for AI agents

Bordfeed is an API-first job feed platform: curated, AI-enriched job data over a REST API.

## If you are an MCP client

The server URL is https://bordfeed.com/api/mcp. Sign in with OAuth 2.1 and PKCE. Use a client ID metadata document or dynamic client registration. The human signs in with Google or an emailed link and picks an organization.

Setup: https://bordfeed.com/docs/mcp

Claude Code and Cursor can use the plugin https://github.com/craftled/bordfeed-plugin.

## If you call the REST API

A person creates a key under https://bordfeed.com/dashboard/organization/api-keys, or an assistant uses the email-code sign-up below. The account needs a verified email. Keys start with `bf_live_`.

Send the key as `Authorization: Bearer <key>` or `x-api-key: <key>`.

JSON responses for feed jobs, JSON export and template preview include `attribution` (`text`, `url`, `logo_url`). Show that credit where you publish the jobs. Optional header `X-Bordfeed-Client: <name>/<version>`, for example `bordful/1.0.0`.

Store it in an env var such as BORDFEED_API_KEY or a secret store. Never paste it into chat or logs.

Check it with `GET https://bordfeed.com/api/v1/billing/balance`.

OpenAPI: https://bordfeed.com/api/openapi.json

## Do not drive the sign-in form

The sign-in and sign-up forms are for people. Bot detection blocks automated browsers other than a few verified assistants, and a person still has to open the emailed link or finish Google sign-in. Do not drive those forms. Use MCP, a key a person creates, or the email-code sign-up below.

## Self-serve sign-up for agents (email code)

This is for an assistant that can read the person's inbox, or for a person who reads the 6-digit code out. It opens a pay as you go workspace for a new address, or adds one API key to an existing account. Only register for a person who asked you to, with their own address or an inbox you were given.

### Register

POST https://bordfeed.com/api/agent/register

```bash
curl -s https://bordfeed.com/api/agent/register \
  -H 'content-type: application/json' \
  -d '{"email":"ada@acme.com","agent_name":"Grok Bot","board_name":"Acme","workspace":"acme"}'
```

Request fields:

- `email` (required).
- `agent_name` (required): 1 to 64 letters, digits, spaces, or `.` `_` `(` `)` `-`. Not a URL or a domain.
- `board_name` (optional): name for a new workspace. It is not put in the email.
- `workspace` (optional): organization id, slug, or name, for an account that already has workspaces.
- `ref`, `utm_source`, `utm_medium`, `utm_campaign`, and `install_id` (optional). Invalid values are ignored. Header `X-Bordfeed-Client: <name>/<version>` is optional, for example `bordful/1.0.0`.
- `template_id` (optional): a feed template id, such as `remote-design`. An unknown or non-string id is ignored. Register does not create a feed.

Response 200: `registration_id`, `email`, `expires_in` (600), and `next`. The same shape is returned whether or not an account already exists.

### Verify

POST https://bordfeed.com/api/agent/verify

```bash
curl -s https://bordfeed.com/api/agent/verify \
  -H 'content-type: application/json' \
  -d '{"registration_id":"<registration_id>","code":"123456","workspace":"acme"}'
```

Request fields:

- `registration_id` (required): the id from register.
- `code` (required): the 6-digit code.
- `workspace` (optional): overrides the workspace sent at register.

Response 200: `api_key` (shown once), `key_id`, `key_name`, `organization` (`id`, `name`), `account` (`created` or `existing`), and `next`. When the registration has a known `template_id`, the body also includes `suggested_feed`: `template_id`, `create` (`POST <base>/api/v1/feeds`), `body`, and `dashboard_url`. A registration without a template id omits `suggested_feed`.

When `suggested_feed` is present, create the feed with the new key: `POST https://bordfeed.com/api/v1/feeds` with the JSON in `suggested_feed.body` (`{"name":"<template name>","template_id":"<id>","filters":{}}`). Empty `filters` keeps the template filters. Send the key as `Authorization: Bearer <key>` or `x-api-key: <key>`. Verify does not create a feed. `dashboard_url` opens the create page in the workspace that is active in the browser, so for an account with several workspaces switch to `organization.name` first, or use the API call, which always uses the key's workspace.

Check the key with `GET https://bordfeed.com/api/v1/billing/balance`.

### Errors

| Code | HTTP | When |
| --- | --- | --- |
| invalid_request | 400 | The body is missing fields or is not valid JSON. |
| invalid_email | 400 | The email shape is wrong, or the domain is disposable. |
| invalid_agent_name | 400 | `agent_name` is empty, too long, or looks like a URL or domain. |
| rate_limit_exceeded | 429 | Too many requests. Honor the Retry-After header. |
| email_send_failed | 502 | The code email could not be sent. Register again. |
| invalid_registration | 404 | No registration has that id. |
| invalid_code | 400 | The code is wrong. `attempts_remaining` says how many tries are left. |
| locked | 423 | Five wrong codes. Register again for a new code. |
| code_expired | 410 | The code is older than 10 minutes, or a newer register replaced it. |
| already_issued | 409 | The key was already returned once. Revoke it in the dashboard if it was lost, then register again. |
| workspace_required | 409 | The account has more than one workspace, or the requested name matches more than one. The body lists `workspaces`. |
| workspace_not_found | 404 | `workspace` is not one of this account's workspaces. The body lists them. |
| account_disabled | 403 | The account is disabled. |
| signup_disabled | 403 | Public sign-up is off, so a new address cannot be created. |

### Limits

- 3 registers per email address per hour, and 5 per day.
- 5 registers per IP per hour, and 20 per day.
- 200 registers per hour across everyone.
- 60 verify attempts per IP per hour.
- The code lasts 10 minutes, works once, and locks after 5 wrong tries.

### What you get

A new account gets a pay as you go workspace, free starting credit once per person, and no card. An existing account gets a new key in the chosen workspace, and every owner of that workspace is emailed.

Store the key in an env var such as BORDFEED_API_KEY or a secret store. Never paste it into chat or logs.

## Billing

Pay as you go starts with free credit once, and no card. When credit runs out the API returns 402 `insufficient_credits` with a `topup_url`.
That link opens Stripe Checkout for a top-up of this workspace. It needs no Bordfeed sign-in and works for about an hour. Open it, or forward it to the person you work for.
Add jobs= to choose 1000, 5000, 10000 or 100000 jobs. The default is 1000.
The link is for pay as you go only. Plans stay in the dashboard.

- https://bordfeed.com/pricing
- https://bordfeed.com/llms.txt

## Revoke

Revoke a key under https://bordfeed.com/dashboard/organization/api-keys. Revoke OAuth clients under https://bordfeed.com/dashboard/settings?tab=sessions.
