25 :: API – SELMA SIS Resource Centre Wed, 20 May 2026 05:22:54 +0000 en-NZ hourly 1 /wp-content/uploads/2022/10/selmalogo.ico 25 :: API – SELMA SIS Resource Centre 32 32 Custom Fields API /custom-fields-api/ /custom-fields-api/#respond Wed, 20 May 2026 05:21:54 +0000 /?p=5596 In this Section:

Custom fields let an organisation attach extra structured data to records such as students, enrolments, intakes, contacts and organisations. Each field has a type (text, number, date, time, check, drop, multi, link or textarea) and is scoped to a particular record type — for example a Student field cannot be written against an Enrolment.

This article covers the API surface for reading custom field definitions and writing custom field values. Field definitions themselves are created and edited in the SELMA admin UI — there is no POST on /api/custom_fields.


Discovering fields

GET /api/custom_fields returns every field defined for your account. Each item exposes the field id, label, api_name, the type (with a code such as drop or text), the object it belongs to (e.g. S for Student), and — for drop and multi fields — a customFieldOptions array of option IRIs.

GET /api/custom_fields/19142

{
  "@id": "/api/custom_fields/19142",
  "id": 19142,
  "label": "Favourite Colour",
  "api_name": "favourite_colour",
  "custom_field_type": { "code": "drop", … },
  "customFieldOptions": [
    "/api/custom_field_options/60792",
    "/api/custom_field_options/60793",
    "/api/custom_field_options/60794"
  ]
}

Filter the collection by api_name, label, custom_field_object, or custom_field_type:

GET /api/custom_fields?api_name=favourite_colour

Discovering options

For drop and multi fields, dereference any IRI from the field’s customFieldOptions array, or query the collection directly:

GET /api/custom_field_options?custom_field=19142

{
  "totalItems": 3,
  "member": [
    {
      "@id": "/api/custom_field_options/60792",
      "id": 60792,
      "custom_field": "/api/custom_fields/19142",
      "code": "red",
      "name": "Red",
      "value": "red",
      "sort_order": 1,
      "active": true
    },
    …
  ]
}

Also filterable by code and active.


Writing values

A custom field value binds a field to a single parent record (such as a student or enrolment) and carries the user’s input in selected_value.

Three things to send on every POST:

  • custom_field — IRI of the field definition.
  • One parent IRI — exactly one of student, enrolment, enrolment_component, intake, intake_component, programme, component, campus, contact, organisation, class, sysuser, application, or placement. It must match the field’s custom_field_object.
  • selected_value — a flat value whose shape depends on the field type.

Shapes for selected_value:

  • text / textarea / link / number — a scalar string.
  • date"YYYY-MM-DD".
  • time"HH:MM" or "HH:MM:SS".
  • check"0", "1", "true" or "false".
  • drop — a single CustomFieldOption IRI.
  • multi — an array of CustomFieldOption IRIs.

Examples

Text field on a Student

POST /api/custom_field_values
Content-Type: application/ld+json

{
  "custom_field":   "/api/custom_fields/19140",
  "student":        "/api/students/800990683",
  "selected_value": "Jane Doe"
}

Drop field on a Student

POST /api/custom_field_values

{
  "custom_field":   "/api/custom_fields/19142",
  "student":        "/api/students/800990683",
  "selected_value": "/api/custom_field_options/60793"
}

Multi field on an Enrolment

POST /api/custom_field_values

{
  "custom_field":   "/api/custom_fields/19150",
  "enrolment":      "/api/enrolments/12345",
  "selected_value": [
    "/api/custom_field_options/60792",
    "/api/custom_field_options/60794"
  ]
}

Updating and clearing

Use PATCH with application/merge-patch+json to change just the value:

PATCH /api/custom_field_values/132719
Content-Type: application/merge-patch+json

{ "selected_value": "/api/custom_field_options/60792" }

To clear a value, send null:

PATCH /api/custom_field_values/132719

{ "selected_value": null }

Rules and validation

  • Exactly one parent IRI per value — zero or two is a 422.
  • The parent’s record type must match the field’s custom_field_object.
  • For drop and multi, the supplied option IRI(s) must belong to that field. A 422 with “…” is not a valid option for this custom field. is returned otherwise.
  • Mandatory fields reject empty selected_value.
  • max_length and validation_regex from the field definition are enforced on text-shaped values.

NOTE: Field definitions and their options are managed in the SELMA admin UI. The API exposes them as read-only resources so integrations can discover what’s available and write values against them.

]]>
/custom-fields-api/feed/ 0
SELMA API User Guide /api/ /api/#respond Wed, 22 May 2024 22:57:03 +0000 /?p=1482
  • Getting Started
  • Authentication
  • Making API Requests
  • Common Operations
  • Error Handling
  • Rate Limiting
  • Best Practices
  • 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:

    1. Navigate to /api/docs in your SELMA instance
    2. Login with your SELMA credentials
    3. Find your API username in the API Users section
    4. Check the safety checkbox to enable the Regenerate button
    5. Click Regenerate
    6. Confirm the action when prompted
    7. IMPORTANT: Copy the generated secret immediately – it will only be shown once!
    8. Click “I have saved the key” to close the dialog
    9. 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):

    1. Follow steps 1-9 above
    2. Warning: Regenerating immediately invalidates your previous secret
    3. 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
    ]]>
    /api/feed/ 0