Digitemp
Contractor job submission and localized option lists use /api/contractor/* (legacy /api/employer/* uses the same handlers). Mediators authenticate with POST /api/mediator/login (Laravel Sanctum bearer token). Example base URL: https://api.digitemp.ch/api or your app host. This page is served at the app root: /.
Replace {prefix} with contractor or employer. Verification is available on both contractor and employer paths.
GET /api/{prefix}/industriesGET /api/{prefix}/professions?industry=<industryKey>GET /api/{prefix}/locationsGET /api/{prefix}/job-typesGET /api/{prefix}/durationsGET /api/{prefix}/qualificationsGET /api/{prefix}/mobility-optionsGET /api/{prefix}/experience-optionsPOST /api/{prefix}/jobsGET /api/contractor/verify/{token} (also /api/employer/verify/{token})POST /api/mediator/login — mediator token (public)GET /api/mediator/cantons — cantons with ≥1 open job (auth)GET /api/mediator/jobs?canton=ZH — open jobs in canton (auth)GET|POST|PATCH|DELETE /api/mediator/candidates … (auth)GET|POST /api/mediator/suggestions (auth)Issues a personal access token for an active user whose role is mediator. This is login only; there is no public signup endpoint on this API.
Content-Type: application/json and (for browser clients) Accept: application/json.personal_access_tokens table (run php artisan migrate after deploying Sanctum).Request body
{
"email": "mediator@example.com",
"password": "your-password"
}
200 — success
{
"token": "1|…plain-text-token…",
"token_type": "Bearer",
"user": {
"id": 1,
"name": "Example Mediator",
"email": "mediator@example.com",
"preferred_lang": "de"
}
}
Use later API calls as: Authorization: Bearer <token> (middleware auth:sanctum on protected routes).
401 — invalid credentials (wrong password, unknown email, user not a mediator, or is_active is false; same message in all cases):
{
"message": "Invalid credentials."
}
422 — validation (e.g. invalid email format, missing password).
All paths below require Authorization: Bearer <token> from login. User must have role: mediator and be active; otherwise 403.
GET /api/mediator/cantons — { "cantons": [ { "code", "name", "open_job_count" } ] }. Names use the user’s preferred_lang (de/fr/en).GET /api/mediator/jobs?canton=ZH — same filter as canton list: status = published, non-empty canton_code, not past expires_at. Query canton or canton_code (2 letters, trimmed, uppercased). Optional page, per_page (max 50). Response: data (job cards) and meta including canton (resolved code), current_page, last_page, per_page, total. Each job includes mobility (localized label from the stored value) and licence_categories (array of licence codes, may be empty).GET /api/mediator/candidates — list candidates where managed_by is the current user.POST /api/mediator/candidates — create; optional skill_ids array of skill IDs to attach. Use driving_licence + licence_categories for mobility. Response includes read-only mobility (localized summary from the licence; do not send mobility or mobility_id on write).GET|PATCH|DELETE /api/mediator/candidates/{id} — detail, update, delete (404 if not owned).POST /api/mediator/suggestions — body { "job_id", "candidate_id" }. Creates a pending suggestion; issues candidate_view_token on the job when missing (employer picker link). 422 with code: DUPLICATE_SUGGESTION if an active suggestion already exists for that job and candidate.GET /api/mediator/suggestions — recent suggestions by this mediator (up to 200).Candidate create request example (POST /api/mediator/candidates):
{
"first_name": "Anna",
"last_name": "Muster",
"birthdate": "1994-03-21",
"address": "Musterstrasse 10, 4051 Basel",
"mobile_number": "+41 79 123 45 67",
"email": "anna@example.com",
"languages": ["de", "en", "fr"],
"driving_licence": true,
"licence_categories": ["B", "BE"],
"hourly_rate": 48.5,
"experiences": [
{ "from_month": "01/2020", "to_month": "12/2023", "description": "4 years in interior masonry" },
{ "from_month": "01/2018", "to_month": "12/2019", "description": "2 years in facade restoration" }
],
"notes": "Available on short notice.",
"is_active": true,
"skill_ids": [1, 3, 7]
}
201 — success:
{
"data": {
"id": 42,
"first_name": "Anna",
"last_name": "Muster",
"full_name": "Anna Muster",
"birthdate": "1994-03-21",
"address": "Musterstrasse 10, 4051 Basel",
"mobile_number": "+41 79 123 45 67",
"email": "anna@example.com",
"languages": ["de", "en", "fr"],
"driving_licence": true,
"licence_categories": ["B", "BE"],
"mobility": "B, BE",
"hourly_rate": 48.5,
"experiences": [
{ "from_month": "01/2020", "to_month": "12/2023", "description": "4 years in interior masonry" },
{ "from_month": "01/2018", "to_month": "12/2019", "description": "2 years in facade restoration" }
],
"skills": ["Maurer", "Sicherheitskenntnisse"],
"notes": "Available on short notice.",
"is_active": true
}
}
422 — validation shape:
{
"message": "The name field is required. (and 1 more error)",
"errors": {
"name": ["The name field is required."],
"canton_code": ["The selected canton code is invalid."]
}
}
Returns available industries with stable keys and multilingual labels.
[
{ "value": "technologie", "label": { "de": "IT & Tech", "en": "IT & Tech", "fr": "IT & Tech" } },
{ "value": "finanzen", "label": { "de": "Finanzen", "en": "Finance", "fr": "Finance" } }
]
Example: /api/contractor/professions?industry=technologie — returns professions allowed for the selected industry key.
[
{ "value": "software-entwickler", "label": { "de": "Software-Entwickler", "en": "Software Developer", "fr": "Developpeur logiciel" } },
{ "value": "projektmanager", "label": { "de": "Projektmanager", "en": "Project Manager", "fr": "Chef de projet" } }
]
Work location list by canton code.
[
{ "value": "ZH", "label": { "de": "Zurich", "en": "Zurich", "fr": "Zurich" } }
]
Job type options (localized labels).
Expected duration options (localized labels).
Fixed list of four options. Submit value in POST /jobs as qualification. Legacy German words may still be accepted server-side; clients should use these keys.
[
{ "value": "skilled", "label": { "de": "Gelernt", "en": "Skilled worker", "fr": "Ouvrier qualifié" } },
{ "value": "semi-skilled", "label": { "de": "Angelernt", "en": "Semi-skilled worker", "fr": "Ouvrier semi-qualifié" } },
{ "value": "professional-worker", "label": { "de": "Berufsarbeiter", "en": "Professional worker", "fr": "Ouvrier de métier" } },
{ "value": "general-laborer", "label": { "de": "Hilfsarbeiter", "en": "General laborer", "fr": "Manœuvre" } }
]
Mobility options (localized labels).
Years of experience options (localized labels).
Creates a pending job, validates industry–profession dependency, and sends the verification email.
industry and professionlicence_categories — array of EU/CH driving-licence codes (A, A1, A2, B, BE, C, C1, CE, C1E, D, D1, DE, G). Multiple selections allowed. Also accepted as a comma-separated string (e.g. "B, BE").201 on success{
"employer_company": "Digitemp AG",
"employer_contact_person": "Max Muster",
"employer_email": "hr@digitemp.ch",
"canton_code": "ZH",
"location": "zurich",
"job_type_id": "1",
"start_date": "2026-04-01",
"duration_id": "1",
"industry": "technologie",
"profession": "software-entwickler",
"qualification": "skilled",
"mobility": "flexibel",
"licence_categories": ["B", "BE"],
"experience_years": "3+",
"remarks": "Optional note",
"employer_lang": "de"
}
{
"message": "Job created successfully"
}
422 returns Validation failed and may return INVALID_PROFESSION_FOR_INDUSTRY for mapping errors.
Verifies a job posting token and publishes the job. Same behavior at /api/employer/verify/{token}.
Accept: application/json for JSON.INVALID_VERIFICATION_TOKENJOB_EXPIREDpublished, expires_at = now + 7 days{
"message": "Validation failed",
"errors": {
"employer_email": ["The employer email field must be a valid email address."],
"industry": ["The industry field is required."]
}
}
{
"code": "INVALID_PROFESSION_FOR_INDUSTRY",
"message": "Profession does not belong to selected industry",
"field": "profession",
"allowedProfessions": [
{ "value": "projektmanager", "label": { "de": "Projektmanager", "en": "Project Manager", "fr": "Chef de projet" } }
]
}
Replace host if needed (examples use https://api.digitemp.ch).
# Option lists (swap /contractor/ for /employer/)
curl -i "https://api.digitemp.ch/api/contractor/industries"
curl -i "https://api.digitemp.ch/api/contractor/professions?industry=technologie"
curl -i "https://api.digitemp.ch/api/contractor/locations"
curl -i "https://api.digitemp.ch/api/contractor/job-types"
curl -i "https://api.digitemp.ch/api/contractor/durations"
curl -i "https://api.digitemp.ch/api/contractor/qualifications"
curl -i "https://api.digitemp.ch/api/contractor/mobility-options"
curl -i "https://api.digitemp.ch/api/contractor/experience-options"
# Create job
curl -i -X POST "https://api.digitemp.ch/api/contractor/jobs" \
-H "Content-Type: application/json" \
-d '{"employer_company":"Digitemp AG","employer_contact_person":"Max Muster","employer_email":"hr@digitemp.ch","canton_code":"ZH","location":"zurich","job_type_id":"1","start_date":"2026-04-01","duration_id":"1","industry":"technologie","profession":"software-entwickler","qualification":"skilled","mobility":"flexibel","licence_categories":["B","BE"],"experience_years":"3+","remarks":"Optional note","employer_lang":"de"}'
# Verify (HTML in browser)
curl -i "https://api.digitemp.ch/api/contractor/verify/YOUR_TOKEN_HERE"
# Verify as JSON
curl -i -H "Accept: application/json" "https://api.digitemp.ch/api/contractor/verify/YOUR_TOKEN_HERE"
# Mediator login (JSON)
curl -i -X POST "https://api.digitemp.ch/api/mediator/login" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"email":"mediator@example.com","password":"your-password"}'
GET and POST routes above exist for both /api/contractor/… and /api/employer/…. Verification: GET /api/contractor/verify/{token} (used in emails) or GET /api/employer/verify/{token}.