An MCP server that cross-searches physicalai-jobs.com × humanoid-jobs.com and also lets you edit your own jobs and profile.
24 read/write + 12 automation, analytics & AI-assist — 37 tools total, callable from Claude Code / Cursor / HTTP API.
The answer to "AI can read the site directly, so why bother with MCP?" For a one-off question it is indeed unnecessary — but for cross-site search, scheduled runs, strict filtering and bulk retrieval it makes a real difference.
| Aspect | Web access (no MCP) | Via MCP |
|---|---|---|
| Data format | LLM parses HTML | Structured JSON returned instantly |
| Response speed | Several to tens of seconds | ~100ms (direct DB) |
| 2-site cross-search | Crawl humanoid and physicalai separately | Both in one request (omit site_code) |
| Filter precision | Only what the UI can show | Strict salary_min / is_remote / prefecture etc. |
| Bulk retrieval | Scraping risks being blocked | All records safely via offset/limit |
| Resilience to site changes | Breaks on layout changes | Stable with a fixed schema |
| Scheduled runs (cron) | Launch a browser every time → slow & heavy | Done with a single curl |
In short: if you "just want to ask AI one thing right now" it is unnecessary. If you want to build it into an automated workflow, aggregate daily, or search both sites accurately at once, MCP is overwhelmingly easier.
Representative scenarios where an AI agent uses job data across physicalai-jobs.com / physicalai-jobs.com.
Scenario: "Find remote jobs in humanoid or physical AI paying ¥8M+."
Action: Just call jobs_search without specifying a site to search both at once.
Scenario: "List all companies like Boston Dynamics with their tech stack and job count."
Action: companies_search → companies_detail to get tech stack and open roles.
Scenario: "Summarize the latest trends in the humanoid industry from articles."
Action: articles_search to fetch articles → articles_detail to analyze the body.
Scenario: "Report the weekly trend of humanoid vs physical-AI job counts."
Action: Just hit stats via a weekly cron and post to Slack.
Connect to Jobs Navi in 3 steps from MCP-capable AI such as Claude Code / Cursor.
/mypage/api-keys/ to generate a key. Skip if you only read. .mcp.json) or Cursor (~/.cursor/mcp.json). env only for those who issued a key. {
"mcpServers": {
"jobs-navi": {
"command": "npx",
"args": ["-y", "jobs-navi-mcp"],
"env": {
"JOBS_NAVI_API_KEY": "jn_your_api_key_here"
}
}
}
}
jobs-navi-mcp via npx. After restart, 37 tools are recognized. # Read example
> Any robotics engineer jobs in Tokyo paying ¥8M+?> List all jobs Boston Dynamics is posting now
# Write example (API key required)
> Create a new job: Senior Robotics Engineer, ¥9M–15M, remote OK> Update our company profile description to "Series B closed in FY2026"> Change my desired salary to ¥9M and set Tokyo/Kanagawa as preferred
Connect three ways: Claude Code / Cursor / HTTP API. With HTTP API you can also call it from ChatGPT Custom GPT Actions.
Add the following to .mcp.json or ~/.claude.json. JOBS_NAVI_API_KEY is required for write tools (optional for read-only).
{
"jobs-navi": {
"command": "npx",
"args": ["-y", "jobs-navi-mcp"],
"env": {
"JOBS_NAVI_API_KEY": "jn_your_api_key_here"
}
}
}
Add the following to ~/.cursor/mcp.json.
{
"mcpServers": {
"jobs-navi": {
"command": "npx",
"args": ["-y", "jobs-navi-mcp"],
"env": {
"JOBS_NAVI_API_KEY": "jn_your_api_key_here"
}
}
}
}
* ChatGPT does not support Remote MCP. Call the HTTP API from Custom GPT Actions.
# Custom GPT Actions setup
# Server URL
https://physicalai-jobs.com/api/mcp.php
# Method: POST / Body example
{
"action": "jobs.search",
"params": { "keyword": "robotics" }
}
Reads need no auth; writes require Authorization: Bearer jn_xxx.
# Read (no auth)
curl -X POST https://physicalai-jobs.com/api/mcp.php \
-H "Content-Type: application/json" \
-d '{"action": "jobs.search", "params": {"keyword": "robot", "limit": 5}}'
# Write (API key required)
curl -X POST https://physicalai-jobs.com/api/mcp.php \
-H "Authorization: Bearer jn_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"action": "jobs.publish", "params": {"id": 15}}'
The 12 read tools need no auth. The 12 write tools (create/update/publish jobs, edit company/seeker profile, etc.) require an API key in jn_xxx format.
After logging in to physicalai-jobs.com, /mypage/api-keys/ generate a key. jn_ + 48 hex chars = 51 chars, up to 5 keys.
For direct HTTP calls, put it in the Authorization header. The Node.js MCP attaches it automatically via the JOBS_NAVI_API_KEY env var.
Authorization: Bearer jn_a1b2c3d4e5f6...
Since the API key is tied to the issuing user, you can update only your own jobs / your own profile. Other companies' jobs are read-only.
For the detailed spec, defense-in-depth and rate limits, see the Security / Rate Limits sections.
All 37 tools. Click to expand parameters and a response example. Omit site_code for cross-site search. Tools marked [API key] are for writes / operating your own resources.
MCP server health check. Returns job/company/article counts per site.
No parameters required.
Response Example{
"success": true,
"data": {
"status": "ok",
"sites": [
{
"site_code": "humanoid",
"name": "ヒューマノイドジョブ",
"domain": "humanoid-jobs.com",
"job_count": 1,
"company_count": 1,
"article_count": 0
},
{
"site_code": "physicalai",
"name": "フィジカルAIジョブ",
"domain": "physicalai-jobs.com",
"job_count": 0,
"company_count": 0,
"article_count": 0
}
]
}
}
Returns the list of cross-searched sites (code, name, domain, theme color).
No parameters required.
Response Example{
"success": true,
"data": [
{
"site_code": "humanoid",
"name": "ヒューマノイドジョブ",
"domain": "humanoid-jobs.com",
"specialty": "ロボット・ヒューマノイド人材特化",
"theme_color": "#0EA5E9"
},
{
"site_code": "physicalai",
"name": "フィジカルAIジョブ",
"domain": "physicalai-jobs.com",
"specialty": "フィジカルAI人材特化",
"theme_color": "#0d9488"
}
]
}
Returns the job category list with job counts.
| Parameter | Type | Required | Description |
|---|---|---|---|
site_code |
string |
humanoid / physicalai (omit for cross-site) |
{
"success": true,
"data": [
{
"site_code": "humanoid",
"slug": "robot-engineer",
"name": "ロボットエンジニア",
"parent_slug": null,
"description": null,
"job_count": 1
}
]
}
Filter-search jobs by keyword, category, prefecture, employment type, remote and salary.
| Parameter | Type | Required | Description |
|---|---|---|---|
site_code |
string |
humanoid / physicalai (omit for cross-site) | |
keyword |
string |
Job title, skill or company name | |
category_slug |
string |
Category slug | |
prefecture |
string |
Prefecture name (e.g. Tokyo) | |
employment_type |
string |
full_time / part_time / contract / freelance / internship | |
is_remote |
boolean |
true = remote-OK only | |
salary_min |
number |
Minimum salary (in 10k JPY) | |
limit |
number |
Result count (default 20, max 100) | |
offset |
number |
Offset (pagination) |
{
"success": true,
"data": {
"total": 11,
"limit": 20,
"offset": 0,
"results": [
{
"id": 1,
"site_code": "humanoid",
"slug": "sample",
"title": "ヒューマノイドロボットエンジニア",
"employment_type": "full_time",
"prefecture": "東京都",
"is_remote": 0,
"salary_min": 6000000,
"salary_max": 12000000,
"company_name": "Sample Robotics"
}
]
}
}
Get full job details (skill requirements, benefits, company info).
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
Job ID (id or slug required) | |
slug |
string |
Job slug | |
site_code |
string |
Target site when using slug |
{
"success": true,
"data": {
"id": 1,
"title": "ヒューマノイドロボットエンジニア",
"description": "...",
"skills_required": [
"ROS2",
"C++",
"Python"
],
"company_name": "Sample Robotics",
"industry": "ロボティクス"
}
}
List of new or featured jobs (for top page / widgets).
| Parameter | Type | Required | Description |
|---|---|---|---|
site_code |
string |
humanoid / physicalai | |
featured_only |
boolean |
true = featured jobs only | |
limit |
number |
Result count |
{
"success": true,
"data": [
{
"id": 1,
"title": "求人例",
"is_featured": 1,
"company_name": "Sample Robotics"
}
]
}
Filter-search companies by keyword and industry (with active job count).
| Parameter | Type | Required | Description |
|---|---|---|---|
site_code |
string |
humanoid / physicalai | |
keyword |
string |
Company name / description keyword | |
industry |
string |
Industry (e.g. Robotics) | |
limit |
number |
Result count (default 20, max 50) |
{
"success": true,
"data": [
{
"id": 1,
"company_name": "Sample Robotics",
"industry": "ロボティクス",
"active_job_count": 3
}
]
}
Company details (tech stack, office images, active job list).
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
Company ID (id or slug required) | |
slug |
string |
Company public slug | |
site_code |
string |
Target site when using slug |
{
"success": true,
"data": {
"id": 1,
"company_name": "Sample Robotics",
"tech_stack": [
"ROS2",
"Python"
],
"active_jobs": [
{
"id": 1,
"title": "エンジニア"
}
]
}
}
Search job-related articles by keyword and category.
| Parameter | Type | Required | Description |
|---|---|---|---|
site_code |
string |
humanoid / physicalai | |
keyword |
string |
Title / body keyword | |
category |
string |
Article category | |
limit |
number |
Result count |
{
"success": true,
"data": [
{
"id": 1,
"title": "業界の最新トレンド",
"category": "trend",
"view_count": 1234
}
]
}
Get article details including the full body.
| Parameter | Type | Required | Description |
|---|---|---|---|
slug |
string |
YES | Article slug |
site_code |
string |
Target site |
{
"success": true,
"data": {
"slug": "example",
"title": "記事タイトル",
"body": "記事本文..."
}
}
Per-site statistics (active jobs, companies, seekers, applications, articles).
| Parameter | Type | Required | Description |
|---|---|---|---|
site_code |
string |
humanoid / physicalai |
{
"success": true,
"data": [
{
"site_code": "humanoid",
"active_jobs": 1,
"companies": 1,
"seekers": 0,
"applications": 0,
"articles": 0
}
]
}
Company posting plan list (plan name, monthly price, job slots, scout slots, features).
| Parameter | Type | Required | Description |
|---|---|---|---|
site_code |
string |
humanoid / physicalai |
{
"success": true,
"data": [
{
"slug": "basic",
"name": "ベーシック",
"price_monthly": 30000,
"job_limit": 3
}
]
}
[API key] Returns the user tied to the API key. Use to verify the connection.
No parameters required.
Response Example{
"success": true,
"data": {
"user_id": 2,
"email": "company@example.com",
"name": "テスト株式会社",
"role": "company"
}
}
[API key / Company] Returns your company's posted jobs (including drafts).
| Parameter | Type | Required | Description |
|---|---|---|---|
status |
string |
draft / active / closed / paused | |
limit |
number |
Result count (default 30, max 100) |
{
"success": true,
"data": [
{
"id": 1,
"title": "求人",
"status": "active",
"view_count": 2
}
]
}
[API key / Company] Create a new job (saved as draft). Publish with jobs_publish.
| Parameter | Type | Required | Description |
|---|---|---|---|
title |
string |
YES | Job title |
category_slug |
string |
YES | Category slug |
description |
string |
YES | Job description body |
employment_type |
string |
full_time / part_time / contract / internship / remote | |
location |
string |
Work location | |
is_remote |
boolean |
Remote OK | |
salary_min |
number |
Minimum annual salary (JPY) | |
salary_max |
number |
Maximum annual salary (JPY) | |
requirements |
string |
Required qualifications | |
preferred |
string |
Preferred qualifications | |
benefits |
string |
Benefits |
{
"success": true,
"message": "求人を下書きとして作成しました",
"data": {
"id": 15,
"slug": "job-abc123",
"status": "draft"
}
}
[API key / Company] Update your job (only specified fields are overwritten).
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
YES | Job ID to update |
title |
string |
Title | |
salary_min |
number |
Minimum annual salary | |
salary_max |
number |
Maximum annual salary | |
description |
string |
Body |
{
"success": true,
"message": "求人を更新しました",
"data": {
"id": 15
}
}
[API key / Company] Publish a job (draft → active).
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
YES | Job ID to publish |
{
"success": true,
"message": "求人を公開しました",
"data": {
"id": 15,
"status": "active"
}
}
[API key / Company] Close a job (active → closed).
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
YES | Job ID to close |
{
"success": true,
"message": "求人を終了しました",
"data": {
"id": 15,
"status": "closed"
}
}
[API key / Company] Get your company profile.
No parameters required.
Response Example{
"success": true,
"data": {
"id": 1,
"company_name": "テスト株式会社",
"industry": "ロボティクス",
"employee_count": "50-100",
"website_url": "https://example.com"
}
}
[API key / Company] Update your company profile (created if not present).
| Parameter | Type | Required | Description |
|---|---|---|---|
company_name |
string |
Company name (required on first creation) | |
company_name_kana |
string |
Furigana (kana) | |
industry |
string |
Industry | |
employee_count |
string |
Employee count (e.g. 50-100) | |
founded_year |
number |
Year founded | |
website_url |
string |
Official site URL | |
logo_url |
string |
Logo URL | |
description |
string |
Company description | |
address |
string |
Address | |
phone |
string |
Phone number | |
contact_person |
string |
Contact person name |
{
"success": true,
"message": "企業プロフィールを更新しました",
"data": {
"id": 1
}
}
[API key / Job seeker] Get your job-seeker profile.
No parameters required.
Response Example{
"success": true,
"data": {
"id": 1,
"full_name": "テスト 太郎",
"prefecture": "東京都",
"experience_years": 5,
"desired_job_category": "robot-engineer",
"is_public": 1
}
}
[API key / Job seeker] Update your profile (created if not present).
| Parameter | Type | Required | Description |
|---|---|---|---|
full_name |
string |
Full name (required on first creation) | |
full_name_kana |
string |
Furigana (kana) | |
birth_year |
number |
Birth year (AD) | |
gender |
string |
male / female / other / prefer_not | |
prefecture |
string |
Prefecture of residence | |
experience_years |
number |
Years of experience | |
current_status |
string |
employed / unemployed / student / other | |
desired_job_category |
string |
Desired job category | |
desired_salary_min |
number |
Desired minimum salary (in 10k JPY) | |
resume_url |
string |
Resume URL | |
pr_text |
string |
Self PR | |
is_public |
boolean |
Whether to expose to companies |
{
"success": true,
"message": "求職者プロフィールを更新しました",
"data": {
"id": 1
}
}
[API key] Application list. Company role: applications to your jobs; seeker role: applications you submitted.
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
number |
Result count (default 30, max 100) |
{
"success": true,
"data": [
{
"id": 1,
"job_id": 1,
"job_title": "エンジニア",
"applicant_name": "テスト太郎",
"status": "pending",
"created_at": "2026-05-01 10:00:00"
}
]
}
[API key / Company] Update the status of an application to your job.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
YES | Application ID |
status |
string |
YES | pending / reviewing / accepted / rejected / withdrawn |
{
"success": true,
"message": "応募ステータスを更新しました",
"data": {
"id": 1,
"status": "accepted"
}
}
[API key] Register a webhook that POSTs on events (max 5).
| Parameter | Type | Required | Description |
|---|---|---|---|
url |
string |
YES | POST target URL (https:// required) |
events |
array |
YES | new_application / application_status_changed / new_scout / job_published / job_closed |
label |
string |
Label for identification |
{
"success": true,
"message": "Webhookを登録しました",
"data": {
"id": 1,
"url": "https://example.com/webhook",
"events": [
"new_application"
],
"secret": "abc123..."
}
}
[API key] List of registered webhooks (with call / failure counts).
No parameters required.
Response Example{
"success": true,
"data": [
{
"id": 1,
"url": "https://example.com/webhook",
"events": [
"new_application"
],
"total_calls": 12,
"total_failures": 0
}
]
}
[API key] Delete a webhook.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
YES | Webhook ID |
{
"success": true,
"message": "Webhookを削除しました",
"data": {
"id": 1
}
}
[API key] Returns your notification list and unread count.
| Parameter | Type | Required | Description |
|---|---|---|---|
unread_only |
boolean |
true = unread only | |
limit |
number |
Result count (default 30) |
{
"success": true,
"data": {
"unread_count": 3,
"items": [
{
"id": 1,
"type": "new_application",
"title": "新着応募がありました",
"is_read": 0
}
]
}
}
[API key] Mark notifications as read (ID array or "all").
| Parameter | Type | Required | Description |
|---|---|---|---|
ids |
mixed |
YES | ID array [1,2,3] or "all" |
{
"success": true,
"message": "全ての通知を既読にしました",
"data": {
"marked": "all"
}
}
[API key / Company] Bulk-create jobs (max 50, each as draft).
| Parameter | Type | Required | Description |
|---|---|---|---|
jobs |
array |
YES | Array of job objects. Each element uses the same fields as jobs_create |
{
"success": true,
"message": "全ての求人を作成しました",
"data": {
"created_count": 50,
"error_count": 0,
"created": [
{
"index": 0,
"id": 15,
"slug": "...",
"title": "..."
}
],
"errors": []
}
}
[API key / Company] Clone an existing job (as draft).
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
YES | Source job ID |
title |
string |
Title of the new job |
{
"success": true,
"message": "求人を複製しました",
"data": {
"id": 20,
"slug": "...",
"cloned_from": 15,
"status": "draft"
}
}
[API key / Company] Per-job views, applications, favorites and CVR.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
Job ID (omit to aggregate all jobs) |
{
"success": true,
"data": {
"total_jobs": 5,
"total_views": 1234,
"total_applications": 42,
"overall_conversion": 3.41,
"jobs": [
{
"id": 1,
"title": "...",
"view_count": 500,
"application_count": 15,
"favorite_count": 23
}
]
}
}
[API key / Company] Returns applicant info in a flat structure (for CSV conversion).
| Parameter | Type | Required | Description |
|---|---|---|---|
job_id |
number |
Filter by a specific job | |
status |
string |
pending / reviewing / accepted / rejected / withdrawn |
{
"success": true,
"data": {
"count": 1,
"applicants": [
{
"id": 1,
"job_title": "ROS2エンジニア",
"applicant_email": "...",
"full_name": "テスト 太郎",
"prefecture": "東京都",
"status": "pending"
}
]
}
}
[API key] Computes salary statistics (median, quartiles) from active jobs on the site.
| Parameter | Type | Required | Description |
|---|---|---|---|
category_slug |
string |
Category slug | |
prefecture |
string |
Prefecture | |
is_remote |
boolean |
Remote OK only |
{
"success": true,
"data": {
"sample_size": 42,
"min": 3000000,
"max": 15000000,
"median": 7500000,
"p25": 5500000,
"p75": 10000000,
"avg": 7800000,
"unit": "円 / 年"
}
}
[API key] Returns jobs similar to the given job (scored).
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
YES | Reference job ID |
limit |
number |
Result count (default 10, max 30) |
{
"success": true,
"data": {
"source_id": 15,
"results": [
{
"id": 18,
"title": "類似求人",
"similarity_score": 85,
"company_name": "Sample"
}
]
}
}
[API key / Company] Scores your job on 10 criteria. Returns grade A-D and improvement hints.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number |
YES | Job ID to score |
{
"success": true,
"data": {
"job_id": 15,
"score": 72,
"grade": "B",
"checks": [
{
"name": "タイトル20文字以上",
"pass": true,
"weight": 10
}
],
"summary": "良好。改善するともっと応募が増えます"
}
}
Returns a per-company hiring-momentum time series (active/new job counts over time, surge flags) with securities (ticker) codes; listed companies linked to ticker/exchange/country.
| Parameter | Type | Required | Description |
|---|---|---|---|
site_code |
string |
humanoid / physicalai / prompters (omit for cross-site) | |
ticker |
string |
Filter by securities code (e.g. TSLA, 7203) | |
company |
string |
Company name keyword (partial match) | |
period |
string |
weekly (default) / monthly | |
group_by |
string |
company (default) / ticker = aggregate by security (merges name variants & sources; members[] lists the components) | |
limit |
number |
Recent periods to return (default 26, max 104) | |
public_only |
boolean |
true = listed companies (ticker-linked) only | |
min_delta_pct |
number |
Surge threshold, period-over-period % (default 50) |
{
"success": true,
"data": {
"as_of": "2026-05-19",
"period": "weekly",
"count": 12,
"top_surging": [
{
"company": "Tesla, Inc.",
"ticker": "TSLA",
"exchange": "NASDAQ",
"country": "US",
"active_delta_pct": 120,
"latest_active": 11,
"latest_new": 6
}
],
"series": [
{
"company": "Tesla, Inc.",
"ticker": "TSLA",
"exchange": "NASDAQ",
"country": "US",
"is_public": true,
"relation": "pure_play",
"site_code": "humanoid",
"latest_active": 11,
"prev_active": 5,
"active_delta_pct": 120,
"latest_new": 6,
"surge": true,
"points": [
{
"period_end": "2026-05-12",
"active_jobs": 5,
"new_jobs": 2
},
{
"period_end": "2026-05-19",
"active_jobs": 11,
"new_jobs": 6
}
]
}
]
}
}
To prevent DoS and abuse, rate limiting is implemented in two tiers: Nginx (L4) + PHP (L7). On exceed, returns HTTP 429 + Retry-After header.
| Endpoint | Limit | Burst | Reason |
|---|---|---|---|
/api/auth.php | 1 req/sec | 5 | Brute-force protection |
/api/mcp.php | 5 req/sec | 20 | DoS protection (per IP) |
| Category | Limit | Identifier |
|---|---|---|
| Unauthenticated Read | 60 req/min | IP address |
| Authenticated Read | 200 req/min | API key ID |
| Write | 30 req/min | API key ID |
# HTTP/2 429
# Retry-After: 32
{
"success": false,
"message": "Rate limit exceeded: write is limited to 30 times per minute",
"retry_after_sec": 32
}
Clients should wait the Retry-After header seconds before retrying.
Security measures required for production are implemented as defense-in-depth.
| Layer | Measure | Detail |
|---|---|---|
| L4 (Nginx) | IP-based rate limiting | Drops excess requests before reaching PHP |
| HTTP Headers | Security headers | HSTS / X-Content-Type-Options / Referrer-Policy / Permissions-Policy / CSP frame-ancestors |
| CORS | Origin whitelist | Allow only physicalai-jobs.com / physicalai-jobs.com / kyuujin.prompters.jp / asi.co.jp |
| L7 auth | API key verification | Bearer + regex match + SHA-256 hash compare (timing-attack resistant) |
| L7 rate limit | Per API key / IP | Separate Read/Write caps; 429 + Retry-After on exceed |
| Role check | company / seeker boundary | Role violation = 403, accessing others' resources = 404 |
| SQL Injection | PDO Prepared Statement | All queries use placeholders; dynamic parts like LIMIT are intval-cast |
| SSRF protection | Webhook URL validation | localhost / 10.x / 192.168.x / 172.16-31.x / 169.254.x / link-local denied |
| Brute-force | Login attempt tracking | Lock 15 min after 5 email / 20 IP failures |
| Session | Cookie hardening | HttpOnly / Secure / SameSite=Lax |
| Error info | Not exposed | Exception details only in error_log; clients get a generic message |
| Item | Value |
|---|---|
| Format | jn_ + hex 48 chars = 51 chars |
| Entropy | 192-bit (24-byte random) |
| Storage | SHA-256 hash (no plaintext) |
| Scope | Only the issuing user's resources |
| Max keys | 5 per user |
| Revocation | Available instantly (/mypage/api-keys/) |
⚠️ If a key may have leaked, revoke it immediately. After revocation the next request returns 401.
Administrators can monitor in real time on this dashboard: /admin/security/
Logs retained 30 days (auto-cleanup via daily cron).
If you find a security vulnerability, please contact security@physicalai-jobs.com . We will provide a patch before disclosure.
On error, returns success: false with an HTTP status code. Exception details are not exposed to clients (generic message only).
{
"success": false,
"message": "slug or id is required"
}
| HTTP | Meaning | Example cause |
|---|---|---|
400 | Bad Request | Missing required params / invalid value / invalid JSON / SSRF-target URL |
401 | Unauthorized | API key invalid / expired / malformed |
403 | Forbidden | Role violation (e.g. a seeker calling a company-only tool) |
404 | Not Found | Resource not found or no edit permission |
405 | Method Not Allowed | Accessed via GET (POST only) |
429 | Too Many Requests | Rate limit exceeded / brute-force lock (see Retry-After) |
500 | Server Error | Internal error (details only in error_log) |
Job listings from leading Physical AI companies (humanoid, industrial robots, AMRs) including Tesla Optimus, Figure 02 and Unitree.
Roles span Physical AI engineers, consultants, AI researchers, operators and more.