Updated on
SELMA API User Guide
To access the SELMA API, your SELMA administrator will create an API user account for you. They will provide you with:
Getting Started
1. Obtaining API Access
To access the SELMA API, your SELMA administrator will create an API user account for you. They will provide you with:
- Your API username in the format: selma_{environment}_{random_string} (e.g., selma_prod_abc123def4)
2. Generating Your Initial API Secret
After your administrator creates your account, you must generate your API secret:
- Navigate to /api/docs in your SELMA instance
- Login with your SELMA credentials
- Find your API username in the API Users section
- Check the safety checkbox to enable the Regenerate button
- Click Regenerate
- Confirm the action when prompted
- IMPORTANT: Copy the generated secret immediately - it will only be shown once!
- Click "I have saved the key" to close the dialog
- Store the secret securely in your application's configuration
3. Regenerating Your API Secret
If you need to regenerate your secret (for security rotation or if compromised):
- Follow steps 1-9 above
- Warning: Regenerating immediately invalidates your previous secret
- Update all applications using the old secret before regenerating to avoid downtime
4. API Documentation Access
The Swagger UI at /api/docs provides:
- Interactive API documentation
- Request/response schema examples
- API specification downloads (JSON, JSON-LD formats)
Authentication
Obtaining a JWT Token
To authenticate with the API, exchange your credentials for a JWT token: Request: POST /api/auth Content-Type: application/json { "username": "selma_prod_abc123def4", "secret": "your-secret" } Response: { "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." }
Using the JWT Token
Include the token in the Authorization header for all subsequent requests: Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9... Token Expiration: JWT tokens expire after a set period. When expired, simply request a new token using the same authentication endpoint.
Making API Requests
Request Format
All API endpoints follow RESTful conventions:
- GET - Retrieve resources
- POST - Create new resources
- PATCH - Update existing resources
- PUT - Replace existing resources
- DELETE - Remove resources
Response Format
By default, responses are in JSON-LD format. You can request different formats:
- /api/students - JSON-LD (default)
- /api/students.json - JSON
- /api/students.jsonld - JSON-LD
Pagination
Collection endpoints are paginated by default (30 items per page): GET /api/students?page=2 Pagination Response: { "@context": "/api/contexts/Student", "@id": "/api/students", "@type": "hydra:Collection", "hydra:totalItems": 150, "hydra:member": [...], "hydra:view": { "@id": "/api/students?page=2", "@type": "hydra:PartialCollectionView", "hydra:first": "/api/students?page=1", "hydra:last": "/api/students?page=5", "hydra:previous": "/api/students?page=1", "hydra:next": "/api/students?page=3" } }
Filtering
Most collections support filtering: # Search by partial name GET /api/students?name=john # Search by exact code GET /api/students?code=STU001 # Filter by date range GET /api/intakes?start_date[after]=2025-01-01&start_date[before]=2025-12-31 # Multiple filters GET /api/organisations?name=university&city=auckland
Common Operations
Creating a Student
POST /api/students Content-Type: application/json Authorization: Bearer {token} { "code": "STU12345", "first_name": "John", "last_name": "Smith", "email": "john.smith@example.com", "date_of_birth": "1995-06-15", "gender": "/api/genders/1", "student_status": "/api/student_statuses/1" }
Creating an Enrolment
POST /api/enrolments Content-Type: application/json Authorization: Bearer {token} { "student": "/api/students/123", "intake": "/api/intakes/45", "start_date": "2025-02-01T00:00:00+13:00", "end_date": "2025-11-30T23:59:59+13:00", "enrolment_status": "/api/enrolment_statuses/1" }
Retrieving Resources by Alternative ID
Some resources support alternative identifiers: # Get student by other_id_1 GET /api/students/other_id_1/{other_id_1} # Get organisation by tax number GET /api/organisations?tax_number=123456789
Error Handling
Error Response Format
Errors follow RFC 7807 Problem Details standard: { "@context": "/api/contexts/Error", "@type": "hydra:Error", "hydra:title": "An error occurred", "hydra:description": "student is already enrolled in this intake", "trace": [...] }
Common Error Codes
- 400 Bad Request - Invalid input data
- 401 Unauthorized - Missing or invalid authentication
- 403 Forbidden - Insufficient permissions or accessing another account's data
- 404 Not Found - Resource doesn't exist
- 422 Unprocessable Entity - Validation errors
- 429 Too Many Requests - Rate limit exceeded
Rate Limiting
The API implements two-tier rate limiting:
- Per Minute: 100 requests per minute (sliding window)
- Per Day: 20,000 requests per day (fixed window)
When you exceed a rate limit, you'll receive a 429 Too Many Requests response. The response headers will indicate when you can retry: X-RateLimit-Limit: 100 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1640995200
Best Practices
1. Secure Your Credentials
- Never commit API secrets to version control
- Use environment variables or secure key management systems
- Rotate secrets regularly (recommended: every 90 days)
2. Handle Errors Gracefully
- Implement retry logic with exponential backoff for 5xx errors
- Log error responses for debugging
- Don't retry 4xx errors without fixing the request
3. Optimize API Usage
- Use filtering to reduce payload sizes
- Cache responses where appropriate
- Batch operations when possible
- Request only the fields you need
4. Monitor Your Usage
- Track your API usage against rate limits
- Set up alerts for approaching limits
- Monitor the "Last API Access" information in the UI
5. Date/Time Handling
- Always include timezone information in date inputs
- Expect UTC times in responses
- Use ISO 8601 format (e.g., 2025-06-06T12:00:00+13:00)
6. IRI References
When referencing related resources, use their IRI (Internationalized Resource Identifier):
- Correct: "student": "/api/students/123"
- Incorrect: "student": 123 or "student_id": 123
Last updated