gohorsejobs/docs/API.md
Tiago Yamamoto 754acd9d3c feat: merge backoffice into settings and add CRUD for credentials
- Move backoffice functionality into settings page as new tab
- Remove standalone backoffice page and sidebar link
- Add edit/delete buttons for credentials management
- Update credentials service to allow overwriting existing credentials
- Add API documentation for system credentials endpoints
2026-02-23 12:42:06 -06:00

13 KiB

📡 GoHorse Jobs - API Documentation

Complete API reference with routes, permissions, and modules.

Last Updated: 2026-02-16
Base URL: https://api.gohorsejobs.com/api/v1
Auth: JWT Bearer Token or HttpOnly Cookie


🔐 Authentication

Methods

  1. Authorization Header: Authorization: Bearer <token>
  2. Cookie: jwt=<token> (HttpOnly, Secure)

Roles

Role Code Level Description
SuperAdmin superadmin 0 Platform administrator
Admin admin 1 Company administrator
Recruiter recruiter 2 Job poster
Candidate candidate 3 Candidate
Guest - - No authentication

📋 Module: Authentication

Login

POST /api/v1/auth/login
Field Auth Roles Description
Public Guest Authenticate user

Request:

{
  "identifier": "lol",
  "password": "Admin@2025!"
}

Response (200):

{
  "token": "eyJhbGciOiJI...",
  "user": { "id": 1, "role": "superadmin", "name": "Dr. Horse Expert" }
}

Register Candidate

POST /api/v1/auth/register
Field Auth Roles Description
Public Guest Register new job seeker

Request:

{
  "name": "John Doe",
  "email": "john@example.com",
  "password": "SecurePass123!"
}

🏢 Module: Companies

Create Company

POST /api/v1/companies
Field Auth Roles Description
Public Guest Register new company

List Companies

GET /api/v1/companies
Field Auth Roles Description
Smart Optional Guest/Admin Public list or admin full list

Update Company Status

PATCH /api/v1/companies/{id}/status
Field Auth Roles Description
Protected superadmin, admin Activate/deactivate company

👥 Module: Users

Get Current User

GET /api/v1/users/me
Field Auth Roles Description
Protected Any authenticated Get current user profile

List Users

GET /api/v1/users
Field Auth Roles Description
Protected superadmin, admin List all users

Create User

POST /api/v1/users
Field Auth Roles Description
Protected superadmin, admin Create new user

Update User

PATCH /api/v1/users/{id}
Field Auth Roles Description
Protected Any authenticated Update user profile

Delete User

DELETE /api/v1/users/{id}
Field Auth Roles Description
Protected superadmin Delete user

List User Roles

GET /api/v1/users/roles
Field Auth Roles Description
Protected superadmin, admin List available roles

💼 Module: Jobs

List Jobs (Public)

GET /api/v1/jobs
Field Auth Roles Description
Public Guest Search and filter jobs

Query Parameters:

Param Type Description
q string Search query (title, description)
location string Filter by location
type string Employment type filter
workMode string onsite, hybrid, remote
page int Page number (default: 1)
limit int Items per page (default: 20)

Get Job by ID

GET /api/v1/jobs/{id}
Field Auth Roles Description
Public Guest Get job details

Create Job

POST /api/v1/jobs
Field Auth Roles Description
Public* admin, recruiter Create new job posting

Update Job

PUT /api/v1/jobs/{id}
Field Auth Roles Description
Public* admin, recruiter Update job posting

Delete Job

DELETE /api/v1/jobs/{id}
Field Auth Roles Description
Public* admin, recruiter Delete job posting

List Jobs for Moderation

GET /api/v1/jobs/moderation
Field Auth Roles Description
Protected superadmin, admin List all jobs for moderation

Update Job Status

PATCH /api/v1/jobs/{id}/status
Field Auth Roles Description
Protected superadmin, admin Approve/reject/close job

Duplicate Job

POST /api/v1/jobs/{id}/duplicate
Field Auth Roles Description
Protected superadmin, admin Duplicate job posting

📝 Module: Applications

Create Application

POST /api/v1/applications
Field Auth Roles Description
Public Guest/JobSeeker Apply to a job

Request:

{
  "job_id": 123,
  "name": "John Doe",
  "email": "john@example.com",
  "phone": "+55 11 99999-9999",
  "message": "I am interested in this position...",
  "resume_url": "https://..."
}

List Applications

GET /api/v1/applications
Field Auth Roles Description
Public admin, recruiter List applications

Get Application by ID

GET /api/v1/applications/{id}
Field Auth Roles Description
Public admin, recruiter Get application details

Update Application Status

PUT /api/v1/applications/{id}/status
Field Auth Roles Description
Public admin, recruiter Update application status

Request:

{
  "status": "hired",
  "notes": "Approved after final interview"
}

Status Values:

  • pending - Awaiting review
  • reviewed - Seen by recruiter
  • shortlisted - Selected for interview
  • rejected - Not selected
  • hired - Offer accepted

🔔 Module: Notifications

List Notifications

GET /api/v1/notifications
Field Auth Roles Description
Protected Any authenticated Get user notifications

🏷️ Module: Tags

List Tags

GET /api/v1/tags
Field Auth Roles Description
Protected superadmin, admin List all tags

Create Tag

POST /api/v1/tags
Field Auth Roles Description
Protected superadmin, admin Create new tag

Update Tag

PATCH /api/v1/tags/{id}
Field Auth Roles Description
Protected superadmin, admin Update tag

👤 Module: Candidates

List Candidates

GET /api/v1/candidates
Field Auth Roles Description
Protected superadmin, admin List all candidates

📊 Module: Audit

List Login Audits

GET /api/v1/audit/logins
Field Auth Roles Description
Protected superadmin, admin Login audit trail

📦 Module: Storage

Generate Upload URL

POST /api/v1/storage/upload-url
Field Auth Roles Description
Protected Any authenticated Get S3 presigned upload URL

Generate Download URL

POST /api/v1/storage/download-url
Field Auth Roles Description
Protected Any authenticated Get S3 presigned download URL

Delete File

DELETE /api/v1/storage/files
Field Auth Roles Description
Protected Any authenticated Delete file from S3

📚 Module: Documentation

Swagger UI

GET /docs/
Field Auth Roles Description
Public Guest Interactive API documentation

🔑 Module: System Credentials

Manage encrypted credentials for external services (Stripe, SMTP, Storage, etc.).

List Configured Services

GET /api/v1/system/credentials
Field Auth Roles Description
Protected superadmin, admin List all configured services (metadata only, no secrets)

Response (200):

{
  "services": [
    {
      "service_name": "stripe",
      "updated_at": "2026-02-23T10:30:00Z",
      "updated_by": "admin-uuid",
      "is_configured": true
    },
    {
      "service_name": "smtp",
      "updated_at": "2026-02-22T14:00:00Z",
      "updated_by": "superadmin-uuid",
      "is_configured": true
    }
  ]
}

Save Credentials

POST /api/v1/system/credentials
Field Auth Roles Description
Protected superadmin, admin Create or update service credentials

Request:

{
  "serviceName": "stripe",
  "payload": {
    "secretKey": "sk_live_xxx",
    "webhookSecret": "whsec_xxx",
    "publishableKey": "pk_live_xxx"
  }
}

Response (200):

{
  "message": "Credentials saved successfully"
}

Supported Services:

Service Name Fields
stripe secretKey, webhookSecret, publishableKey
smtp host, port, username, password, from_email, from_name, secure
storage endpoint, region, bucket, accessKey, secretKey
cloudflare_config apiToken, zoneId
firebase serviceAccountJson (JSON string)
appwrite endpoint, projectId, apiKey
lavinmq amqpUrl
cpanel host, username, apiToken

Delete Credentials

DELETE /api/v1/system/credentials/{serviceName}
Field Auth Roles Description
Protected superadmin, admin Delete service credentials

Response (200):

{
  "success": true
}

Security Notes:

  • Credentials are encrypted with RSA-OAEP-SHA256 before storage
  • Only metadata (service name, timestamps) is returned on list operations
  • Actual secret values cannot be retrieved after saving
  • Updating credentials overwrites the existing configuration

🔑 Permission Matrix

Route Guest JobSeeker Recruiter CompanyAdmin Admin SuperAdmin
POST /auth/login
POST /auth/register
GET /jobs
GET /jobs/{id}
POST /jobs
POST /applications
GET /users/me
GET /users
DELETE /users/{id}
GET /notifications
GET /audit/logins
GET /jobs/moderation

🆔 ID Formats

Entity ID Type Example
Users INT (SERIAL) 1, 42, 1337
Companies INT (SERIAL) 1, 15, 100
Jobs INT (SERIAL) 1, 500, 2500
Notifications UUID v7 019438a1-2b3c-7abc-8123-4567890abcdef
Tickets UUID v7 019438a2-3c4d-7xyz-9abc-def0123456789
Payments UUID v7 019438a3-4e5f-7mno-pqrs-tuvwxyz012345

📝 Error Responses

400 Bad Request

{
  "error": "Invalid request body",
  "details": "Field 'email' is required"
}

401 Unauthorized

{
  "error": "Unauthorized",
  "message": "Invalid or expired token"
}

403 Forbidden

{
  "error": "Forbidden",
  "message": "Insufficient permissions"
}

404 Not Found

{
  "error": "Not Found",
  "message": "Resource not found"
}

500 Internal Server Error

{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred"
}