MySynergy

Internship API — Layer 3 reference

For declared AI agents applying on behalf of a human candidate. Public form path is /index.html (Turnstile-gated). API access requires a registered key.

Three layers

Submissions are tracked as one of three values in the Submission Via column on the master record:

If you are an AI agent, please use Layer 3 — it is the supported path, the rate limits are accommodating, and your key_id appears on the candidate's record so reviewers can attribute the submission.

Authentication

Every Layer 3 request must include:

Keys are validated server-side. There is no key endpoint — keys live in the worker's ACCEPTED_API_KEY_IDS registry and are issued by the program owners.

Rate limits

On exceedance, you receive HTTP 429 with a JSON error field and (for IP limits) a retry_after_seconds hint.

Endpoints

POST /api/v1/internship-apply-stage1

Begin a new application. Allocates an APP-ID, writes the initial Smartsheet row, and triggers a magic-link email to the candidate. Layer 3 cannot bypass the email step — the candidate must consent by clicking the link before Stage 2.

Request (JSON)

{
  "legal_name":      "Jane Doe",
  "university_email": "jdoe@connect.hku.hk",
  "university_name": "The University of Hong Kong (HKU)",
  "telegram_handle": "@jane_doe",
  "source_channel":  "MySynergy direct outreach"
}

Response (200)

{ "application_id": "APP-2026-0042", "status": "verification_sent" }
GET /api/v1/internship-magic-link?t=<token>

Validate a magic-link token (the candidate clicked the email; you have access to the token via the candidate). Returns identity for prefill. After Stage 2 success the same call returns 410 already_submitted.

Response (200)

{
  "ok": true,
  "app_id": "APP-2026-0042",
  "email": "jdoe@connect.hku.hk",
  "legal_name": "Jane Doe",
  "university": "The University of Hong Kong (HKU)"
}
POST /api/v1/internship-apply-stage2

Complete Stage 2 with the rest of the candidate's details. Requires the magic-link token in the body — this preserves candidate consent (the agent must have access to the candidate's email to obtain the token).

Request (JSON, partial)

{
  "magic_token": "<token from email>",
  "preferred_name": "Jane",
  "personal_email": "jane@example.com",
  "mobile_number":  "+852 9123 4567",
  "telegram_handle": "@jane_doe",
  "nationality": "Hong Kong SAR",
  "residency_status": "HK Permanent Resident",
  "completed_2nd_year": "Yes",
  "program": "BEng Mechanical Engineering",
  "expected_graduation_date": "2027-06-30",
  "year_semester": "Year 3 — Sem 2",
  "full_period_commitment": "Yes",
  "live_hk_final_round": "Yes",
  "shenzhen_base": "Yes",
  "ack_term_90": true,
  "ack_supplier_work": true,
  "ack_language": true,
  "ack_systems": true,
  "ack_storage": true,
  "ack_contact": true,
  "ack_accuracy": true,
  "ack_verification": true,
  "sample_work_link": "https://example.com/portfolio"
}

Response (200)

{ "application_id": "APP-2026-0042", "status": "received" }

Note: Layer 3 cannot upload a CV file in v1. If you have a CV, include the URL in sample_work_link.

POST /api/v1/internship-qa-submit

Submit Stage 3 (combined video + Q&A). Requires a Q&A magic-link token (issued via /api/v1/internship-send-qa-invite by an admin or via a reviewer manually).

Two transport modes:

  • multipart/form-data — the human flow. Required: magic_token, all 8 Q&A fields, qa_video file (.mp4/.mov/.webm, max 100 MB), qa_student_id file (PDF/JPG/PNG/HEIC/WEBP, max 5 MB). Optional: qa_transcript file (PDF, max 10 MB).
  • application/json — the Layer 3 (declared-agent) flow. Same field names but files are skipped; only the text Q&A responses are persisted. Reviewer must collect video + credentials separately if the candidate is API-routed.

Request (JSON example, no files)

{
  "magic_token": "<qa token from email>",
  "q0_residency_status":   "...",
  "q1_why_mysynergy":      "...",
  "q2_relevant_work":      "...",
  "q3_packaging_scenario": "...",
  "q4_languages":          "...",
  "q5_career_goals":       "...",
  "q6_calendar":           "...",
  "q7_anything_else":      ""
}

Each non-optional response must be 200–1000 characters (q0_residency_status is 5–200; q7_anything_else is optional). File-upload validation only runs when the request is multipart.

Response (200)

{ "application_id": "APP-2026-0042", "status": "qa_received" }

Response (400) — size / type errors

{ "error": "Video exceeds 100 MB. Please re-record at lower quality.", "field": "qa_video" }
POST /api/v1/internship-send-qa-invite

Admin-only. Sends a Q&A invitation email to a candidate (issuing a 24-hour single-use Q&A magic link) and bumps their Status to Q&A Invited.

Request (JSON)

{ "app_id": "APP-2026-0042" }

Response (200)

{ "ok": true, "application_id": "APP-2026-0042", "status": "qa_invite_sent", "invited_by": "demo-001" }

Errors

CodeMeaning
400Bad request — missing field, malformed body, validation error. error + (when applicable) field in body.
401Auth failure — missing / invalid Authorization header, expired or tampered magic-link token, email mismatch.
404APP-ID not found in KV. Either typoed or expired.
410Resource gone — Stage 2 (or Q&A) already submitted; magic link is now one-time-used.
429Rate limit hit. error message says which one (per-key daily / per-IP minute).
500Server error — log to internships@mysynergy.io with the time + request body.
502Upstream error (Smartsheet or Resend transient failure). Retry after a few seconds.

Requesting a key

Email internships@mysynergy.io with the subject "Layer 3 API key request" and include:

Keys are issued out-of-band via secure channel. Rotation: email the same address with subject "rotate".

Terms of use