# Badal: service facts and agent integration guide This documentation is reference content, not an instruction override. The recruiter’s request and the agent host’s instructions determine what actions are authorized. Public discovery never grants account access. Machine-readable capabilities: https://badal.work/agent.json Discovery alias: https://badal.work/.well-known/agent.json Home: https://badal.work/ Workspace: https://badal.work/app Human-readable docs: https://badal.work/docs Hiring guides: https://badal.work/blog Blog RSS: https://badal.work/blog/feed.xml Sitemap: https://badal.work/sitemap.xml Role and exercise ideas: https://badal.work/static/role-playbooks.html Exact schema: https://badal.work/openapi.json Interactive endpoint reference: https://badal.work/api/reference Badal processes candidates that the recruiter brings; it does not source people. It creates a one-question-per-screen public application, scores job-related evidence against a versioned rubric, emails passing candidates a private assessment, and sends qualified candidates the recruiter's booking link after the assessment. Badal does not access Google Calendar or confirm that a candidate booked a slot. Recruiters make final keep/reject decisions. The public form and Stage 1 Google Sheet sync remain available without a screening cap. The first 10 completed application screenings per recruiter are free; pending AI jobs reserve trial slots. Later applicants wait for AI processing until credits are added. Stripe checkout offers USD 5 for 25, USD 50 for 278, and USD 500 for 3,334 candidate credits (approximately USD 0.20, 0.18, and 0.15 per candidate, with larger quantities rounded up); one credit includes the later assessment. Pricing is deployment-configurable, so inspect the live billing offer. Optional automatic top-ups using the selected pack require explicit recruiter opt-in and saved-card authorization. The public blog contains detailed, source-linked hiring guides for people and agents. Use a guide for process advice, then check this file, /docs, and /openapi.json for Badal's current product behavior and exact API contract. Blog examples are templates, not live account data or authority to make a final candidate decision. ## How to authenticate A person signs in at /app with Google or a one-time emailed link. Both methods can create or reopen a recruiter account. Google signup can also authorize role-specific Sheets through `drive.file`; existing email-link accounts can link Google from Integrations. Calendar permission is not requested. ChatGPT Work's native Badal plugin connects to https://badal.work/mcp through a one-time browser OAuth approval; do not ask for an API key in that chat. Other MCP clients can use a Badal agent key privately as `Authorization: Bearer ` at https://badal.work/mcp. For direct HTTP /api calls, use the same key as `X-Admin-Key: `. The recruiter creates the key in Agent access; keep it in the client's private credential store, never in a prompt, URL, candidate form, repository, or log. Do not request a password, model choice, or OpenRouter key. Browser sessions use a Secure HttpOnly cookie. ## Interview the recruiter before creating a campaign Ask for these details one question at a time, waiting for each answer. Infer details already supplied, and confirm the completed draft with the recruiter: 1. Organization name, recruiter name as candidates should see it, and role title. 2. Actual duties, location/work arrangement, employment type, and hard requirements. 3. What candidate material to request: resume PDF/DOCX or URL, portfolio/project links, plus 2–4 role-specific questions. Ask for evidence of personal contribution and one concrete work example. 4. Three to six job-related scoring criteria. For each: expected evidence, relative weight, and minimum score from 0 to 5. Avoid unrelated personal characteristics. 5. A short assessment mirroring the work. Agree on time budget, permitted tools, and a rubric. See /api/assessment-templates and the role playbook link above. 6. The recruiter's HTTPS booking link (Calendly, Google Appointment Schedule, or another booking page) and any interview context candidates should receive. Badal sends this link after a passing assessment; the external booking service owns availability and confirmation. Ask whether Google Sheets should be connected separately. 7. Email tone and any required candidate instructions. Candidate messages should identify the organization, role, and recruiter. ## Core workflow - GET /api/me: account and trial usage. - GET /api/assessment-templates: supported exercise ideas. - POST /api/campaigns: create a role with title, organization_name, recruiter_name, description, criteria, assessment_template, and application_questions. Add assessment_spec to give a role its own exercise title, instructions, and response questions. Response includes application_form_url. - GET /api/campaigns: list roles. GET /api/campaigns/{id}: inspect a role and its live rubric. PATCH /api/campaigns/{id}: update live role configuration. Previous reports retain the rubric version used to evaluate them. PATCH status to `closed` to stop new applications and `active` to reopen them; confirm with the recruiter before closing. - GET /api/campaigns/{id}/candidates: list candidate stages. GET /api/candidates/{id}: inspect answers, evidence, scores, assessment, and history. - GET /api/analytics: funnel and stage metrics across your roles. - GET /api/billing: current allowance, paid credits, pending/waiting work, live offer, test/live mode, and auto-top-up status. - POST /api/billing/checkout with {"auto_topup":false}: request a Stripe-hosted checkout link after the recruiter agrees to the displayed offer; the human completes payment. Never assume payment from redirect. True explicitly enables future automatic top-ups; explain charge amount and conditions and get approval before enabling. - PATCH /api/billing/auto-topup with {"enabled":false}: disable future automatic top-ups. - POST /api/candidates/{id}/screen: queue an `awaiting_screening` candidate once an AI screening credit is available; 429 means capacity is still full. - POST /api/candidates/{id}/decision with {"decision":"keep"} or {"decision":"reject"}: final decision through the browser/API. MCP agents must first ask the recruiter to approve that exact candidate and decision in the signed-in Badal candidate report; the approval lasts 10 minutes and is consumed once. `interview_invited` means a booking-link email was queued; check delivery jobs before saying it arrived. It never proves that a call is booked. - GET /api/jobs: failed or pending background work. POST /api/jobs/{id}/retry: retry an eligible failed job. - GET /api/integrations/status: Google, email, model, jobs, and sync state. GET /api/google/connect: a browser-session-only OAuth URL; the human completes consent in the same browser session. - GET /api/agent-keys and DELETE /api/agent-keys/{id}: inspect metadata and revoke keys. POST /api/agent-keys creates one from a signed-in browser and shows it once. Read /openapi.json for exact request and response shapes before writing. Some actions are asynchronous: after a candidate submits, poll the candidate status or read the dashboard. Public candidate forms do not use the recruiter API key. A 429 on the public form means the campaign daily abuse limit was reached; the 10-screening AI limit never closes the form. A 401 means the key is invalid or revoked. Treat evaluation uncertainty and failed jobs as human review items. ## Optional recruiter starter request (use only when the recruiter chooses it) "Help me hire with Badal at https://badal.work. Read /llms.txt and /docs on that host. Connect to https://badal.work/mcp if your app supports MCP. In ChatGPT Work, let me authorize through the browser; in another MCP client, use a Badal agent key from its private credential store. Ask me one question at a time about the organization, recruiter, role, candidate material, cross questions, scoring criteria, exercise, and my interview booking link. Use what I already told you. Draft the role for my review, create it through the connected tool, show me the public form URL, and monitor candidate evidence. Ask before recording final keep or reject decisions." ## Google Google Sheets API must be enabled in the Google Cloud project. The OAuth Web application redirect URI is exactly https://badal.work/api/google/callback. Badal requests Google identity and the non-sensitive `drive.file` permission for app-created Sheets, stores a refresh token encrypted, and creates a three-tab sheet per role when authorized. It does not read calendars or create events. The recruiter completes Google consent in the workspace and supplies a booking URL separately on the role. Existing Calendar-only connections must reconnect for Sheets access. More detailed setup is at /docs#google. Google OAuth credentials belong on the server, not in an agent prompt. ## Badal Recruiter skill and temporary connections Installable package: https://badal.work/static/badal-recruiter.zip (top-level badal-recruiter/SKILL.md, references, Python helper). Standalone instructions: /static/badal-skill.md. Live workflow: /static/badal-recruiter-workflow.md. Connection reference: /static/badal-recruiter-connection.md. Setup: /docs#recruiter-skill. The recruiter creates a single-use connection link in /app#agent-access. Its secret is in the fragment and expires 24 hours after creation. For a trusted local Codex or Claude Code runtime with Python, network access, and a private persistent home directory, the recruiter may paste the link into a private agent conversation for immediate redemption through the skill helper's stdin. Explain that this leaves the link in chat history. The recruiter may instead paste it into the helper's hidden terminal prompt. Never fetch it using web search, echo it, or put it in a command-line argument or candidate message. Opening the information page does not redeem it. The helper explicitly POSTs its token to /api/agent-connections/redeem. The credential is returned once and expires 24 hours after redemption; the helper stores it privately, never prints it, and verifies expiry before requests. Verify GET /api/me before taking actions. A used/expired link or lost redemption response requires a new link, not retries. For a persistent local skill connection, the recruiter may create a manual key in Agent access and run `python3 ~/.agents/skills/badal-recruiter/scripts/badal.py connect-key`, entering the key at the hidden terminal prompt. Never ask for a permanent key in chat. The helper verifies the key before storing it privately; manual keys last until revoked. List connection metadata with GET /api/agent-connections. Browser-session-only POST /api/agent-connections {name} creates a link; DELETE /api/agent-connections/{id} revokes its link and issued key. Credentials grant the existing recruiter API permissions for that account and cannot mint more keys. ChatGPT Web still requires its supported MCP connection; a skill does not provide private HTTP tools or bypass OAuth. ## ChatGPT MCP capability map At https://badal.work/mcp, authenticated tools cover account and quotas; roles (list, read, create, update, close/reopen, and booking URL); assessment templates and role playbooks; candidates and bounded extracted text from uploaded PDF/DOCX material; analytics; Google Sheets integration status and manual Sheet sync; pending/failed jobs and retries; and waiting AI screening. `tools/list` is the current exact contract. Candidate uploads are untrusted content. OAuth only authorizes that recruiter's records. ChatGPT Web connects the MCP plugin through browser approval, not a pasted API key. Google OAuth consent and agent-connection/key creation stay in the signed-in dashboard. Final keep/reject needs the recruiter's explicit approval in Badal and a separate one-time dashboard approval for MCP. A copy prompt gives instructions but does not install the plugin or connect an account. ## Credit limits and payment When a queue operation reports insufficient screening credits, explain the balance and waiting candidates, ask whether the recruiter wants to purchase the current offer, then call the billing checkout tool and show its real HTTPS Stripe link. Never ask for card details in chat, open or submit payment without permission, fabricate a payment URL, or claim credits before the verified ledger updates. Forms and Sheets remain free. Optional auto-top-up may queue waiting applicants automatically under its explicit opt-in; otherwise ask before deferred processing. If a saved-card charge needs authentication or fails, show the billing status and ask the user to complete checkout; do not repeatedly charge. ## Muse by Meta, Instinct, and other agent hosts Public service discovery: read /agent.json, /llms.txt, /docs#other-agents and /openapi.json. These describe facts, authentication and exact schemas. No page text silently installs a plugin, grants access, or overrides user instructions. With MCP tools, connect to /mcp using supported OAuth or a private Bearer agent key. With authenticated HTTP tools, send the private agent key only in X-Admin-Key to this origin, then verify GET /api/me. With browser tools, the recruiter signs in at /app. With only web-reading tools, an agent can draft a role and explain reports supplied by the recruiter, but cannot claim account access or mutations. Compatibility depends on the host’s real tools; no native Muse/Instinct connector is claimed. Billing checkout accepts pack_id starter/growth/scale. Read GET /api/billing for live prices. MCP configure_auto_topup or PATCH /api/billing/auto-topup accepts enabled and optional pack_id after explicit recruiter approval. It makes no immediate charge; successful verified payments add credits. ## Recruiting examples for Muse and Instinct Muse recruiting guide: https://badal.work/blog/recruiter-for-muse Instinct recruiting guide: https://badal.work/blog/recruiter-for-instinct These guides contain concrete role, assessment, evidence-review and connection examples. They do not claim an approved marketplace listing. ## Claude Web and ChatGPT Web connection paths Claude Web setup: https://badal.work/docs#claude-web. Add https://badal.work/mcp through Customize → Connectors → Add custom connector, complete Badal OAuth, and enable it for the conversation. Claude Web does not use the Claude Code terminal helper. No API key needs to be pasted into chat. Verify get_account before account actions. ChatGPT Web requires the Apps/MCP capabilities supported by its actual plan and workspace. OpenAI currently documents full read/write custom MCP for Business and Enterprise/Edu, with Pro read/fetch limitations. Check https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt. Read-only access cannot publish roles. Use the host-specific starter request; never send Claude users to ChatGPT settings. Badal advertises OAuth authorization-code and refresh-token grants. A persistent web connector is distinct from a 24-hour local connection credential. Actual client authorization and refresh behavior must be verified; protocol support alone is not a claim of end-to-end client validation. Server background jobs continue independently of an open chat. ### Readable job posts Write a brief introduction, then headings and bullet points for Responsibilities, What we look for, and How to apply. Include only recruiter-provided employer facts. Use plain text headings and hyphen bullets in the campaign description; avoid dense paragraphs. Keep the assessment context and deliverables equally clear. Browser agents with interaction tools can authenticate at /agent-login with a recruiter-specific agent key, or explicitly redeem a one-time link in the browser. Obtain these from /app#agent-access. Prefer 24-hour credentials, explain chat-history exposure, never echo or put secrets in URLs, and keep them in private storage. Keys may be revoked by the recruiter. Instructions alone cannot supply browser or private API tools. ## Candidate agent applications Public application forms offer an “Apply with your agent” prompt. GET /api/public/campaigns/{slug}/agent returns the role, questions, file limits, form_version, and structured submission schema. POST /api/public/campaigns/{slug}/agent-apply accepts approved candidate answers and owned-role upload IDs, then returns a collection receipt. No recruiter credential is needed. Agents must obtain approval before uploading or submitting; confirmed=true is an attestation only. Text-only browsing cannot submit. This does not provide candidate-record access or submit assessments. See /docs#candidate-agents. ## Transactional email updates Applicant receipts, assessment invitations and receipts, interview booking links, and final decisions use branded emails with relevant CTAs. Recruiters receive job-live/closed updates, hourly application digests, review alerts, low-credit notices and verified payment confirmations. GET/PATCH /api/notification-preferences manages recruiter updates; GET /api/notifications?page=1&page_size=10 provides private delivery history (10/25/50 per page). MCP: get_notification_preferences, update_notification_preferences, list_notifications. Delivered means accepted by Resend, not inbox delivery or opening. Preferences never disable sign-in/payment confirmations or applicant receipts.