Development: http://localhost:8080/api
Production: https://api.glorylabs.nl/api
All protected endpoints require a JWT token in the Authorization header:
Authorization: Bearer <jwt_token>
GET /jobs
Query Parameters: | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | page | integer | 0 | Page number (0-indexed) | | size | integer | 10 | Items per page | | sortBy | string | createdAt | Sort field | | sortDirection | string | DESC | Sort direction (ASC/DESC) |
Response:
{
"content": [
{
"id": 1,
"title": "Senior Java Developer",
"company": "Tech Corp",
"location": "Amsterdam",
"type": "Full-time",
"category": "IT",
"level": "Senior",
"description": "...",
"salaryRange": "€70,000 - €90,000",
"tags": ["Java", "Spring", "Microservices"],
"publishedAt": "2024-09-21T10:00:00",
"viewCount": 42,
"applicationCount": 5
}
],
"totalElements": 100,
"totalPages": 10,
"size": 10,
"number": 0
}
GET /jobs/search?query={searchTerm}
Query Parameters: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | query | string | Yes | Search term | | page | integer | No | Page number | | size | integer | No | Items per page |
Example:
GET /jobs/search?query=java%20developer&page=0&size=20
Response: Same structure as List All Jobs
POST /jobs/filter
Request Body:
{
"location": "Amsterdam",
"type": "Full-time",
"category": "IT",
"level": "Senior",
"searchTerm": "java"
}
Query Parameters: | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | page | integer | 0 | Page number | | size | integer | 10 | Items per page |
Response: Same structure as List All Jobs
GET /jobs/{id}
Path Parameters:
id - Job ID (integer)Response:
{
"id": 1,
"title": "Senior Java Developer",
"company": "Tech Corp",
"location": "Amsterdam",
"type": "Full-time",
"category": "IT",
"level": "Senior",
"description": "Full job description...",
"requirements": "- 5+ years Java experience\n- Spring Boot expertise",
"responsibilities": "- Design and develop APIs\n- Code reviews",
"benefits": "- Competitive salary\n- Remote work options",
"salaryRange": "€70,000 - €90,000",
"tags": ["Java", "Spring", "Microservices"],
"active": true,
"publishedAt": "2024-09-21T10:00:00",
"expiresAt": "2024-10-21T10:00:00",
"viewCount": 42,
"applicationCount": 5
}
POST /jobs
Request Body:
{
"title": "Senior Java Developer",
"company": "Tech Corp",
"location": "Amsterdam",
"type": "Full-time",
"category": "IT",
"level": "Senior",
"description": "We are looking for...",
"requirements": "Required skills...",
"responsibilities": "Your responsibilities...",
"benefits": "We offer...",
"salaryRange": "€70,000 - €90,000",
"tags": ["Java", "Spring", "Microservices"],
"expiresAt": "2024-10-21T10:00:00"
}
Response: Created job object with generated ID
PUT /jobs/{id}
Path Parameters:
id - Job ID to updateRequest Body: Same as Create Job
Response: Updated job object
DELETE /jobs/{id}
Path Parameters:
id - Job ID to deleteResponse: 204 No Content
GET /jobs/filters
Response:
{
"locations": ["Amsterdam", "Rotterdam", "Utrecht", "Remote"],
"categories": ["IT", "Finance", "Marketing", "Sales"],
"types": ["Full-time", "Part-time", "Contract", "Freelance"],
"levels": ["Junior", "Mid-level", "Senior", "Lead", "Manager"]
}
GET /jobs/statistics
Response:
{
"totalActiveJobs": 150,
"jobsLastWeek": 12,
"jobsLastMonth": 45,
"recentJobs": [
{
"id": 1,
"title": "Senior Java Developer",
"company": "Tech Corp",
"publishedAt": "2024-09-21T10:00:00"
}
]
}
POST /crawler/crawl
Request Body:
{
"url": "https://careers.example.com",
"crawlType": "DEEP_CRAWL",
"maxPages": 50,
"initiatedBy": "admin@glorylabs.nl"
}
Crawl Types:
SINGLE_PAGE - Crawl only the specified URLSITEMAP - Crawl based on sitemapDEEP_CRAWL - Deep crawl following linksResponse:
{
"crawlJobId": 123,
"status": "INITIATED",
"message": "Crawl job initiated successfully"
}
GET /crawler/status/{id}
Path Parameters:
id - Crawl job IDResponse:
{
"id": 123,
"url": "https://careers.example.com",
"status": "RUNNING",
"crawlType": "DEEP_CRAWL",
"maxPages": 50,
"pagesProcessed": 12,
"jobsFound": 8,
"jobsCreated": 6,
"createdAt": "2024-09-21T10:00:00",
"startedAt": "2024-09-21T10:00:05",
"completedAt": null,
"errorMessage": null
}
Status Values:
PENDING - Job created but not startedRUNNING - Currently processingCOMPLETED - Successfully finishedFAILED - Error occurredGET /crawler/history
Query Parameters: | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | page | integer | 0 | Page number | | size | integer | 10 | Items per page |
Response:
{
"content": [
{
"id": 123,
"url": "https://careers.example.com",
"status": "COMPLETED",
"pagesProcessed": 50,
"jobsCreated": 25,
"createdAt": "2024-09-21T10:00:00",
"completedAt": "2024-09-21T10:15:00"
}
],
"totalElements": 50,
"totalPages": 5
}
POST /crawler/scrape
Request Body:
{
"url": "https://careers.example.com/job/123",
"createJob": true,
"company": "Example Corp",
"location": "Amsterdam"
}
Response:
{
"success": true,
"title": "Senior Developer Position",
"content": "Scraped content in markdown...",
"url": "https://careers.example.com/job/123"
}
POST /applications
GET /applications/{id}
GET /applications
POST /auth/login
POST /auth/refresh
POST /auth/logout
All endpoints return consistent error responses:
{
"timestamp": "2024-09-21T10:00:00",
"status": 400,
"error": "Bad Request",
"message": "Invalid input parameters",
"path": "/api/jobs/search"
}
{
"timestamp": "2024-09-21T10:00:00",
"status": 401,
"error": "Unauthorized",
"message": "JWT token is expired or invalid",
"path": "/api/jobs"
}
{
"timestamp": "2024-09-21T10:00:00",
"status": 403,
"error": "Forbidden",
"message": "Insufficient permissions",
"path": "/api/jobs/123"
}
{
"timestamp": "2024-09-21T10:00:00",
"status": 404,
"error": "Not Found",
"message": "Job not found with id: 999",
"path": "/api/jobs/999"
}
{
"timestamp": "2024-09-21T10:00:00",
"status": 500,
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"path": "/api/jobs"
}
API rate limits (when implemented):
Rate limit headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1695289200
All list endpoints support pagination with these parameters:
page - Page number (0-indexed)size - Items per page (max 100)sort - Sort field and direction (e.g., "title,asc")Pagination response includes:
content - Array of itemstotalElements - Total number of itemstotalPages - Total number of pagessize - Items per pagenumber - Current page numberfirst - Is first pagelast - Is last pageCORS is configured for:
http://localhost:4200application.ymlAllowed methods: GET, POST, PUT, DELETE, OPTIONS
Allowed headers: All headers
Credentials: Allowed
# Get all jobs
curl -X GET http://localhost:8080/api/jobs
# Search jobs
curl -X GET "http://localhost:8080/api/jobs/search?query=java"
# Get job details
curl -X GET http://localhost:8080/api/jobs/1
# Start a crawl (requires auth)
curl -X POST http://localhost:8080/api/crawler/crawl \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"url":"https://example.com/careers","maxPages":10}'
Import the Postman collection from /docs/postman-collection.json (to be created)
Access Swagger UI at: http://localhost:8080/api/swagger-ui.html (when configured)
Webhook events will be sent for:
Webhook payload format:
{
"event": "job.created",
"timestamp": "2024-09-21T10:00:00",
"data": {
"jobId": 123,
"title": "Senior Developer",
"company": "Tech Corp"
}
}
Reacties