FAQ | This is a LIVE service | Changelog

Skip to content

Implement CHRIS/CAMSIS → CRSid mapping API endpoints (POST create, GET read)

As an integration developer consuming the Identifiers API,
I would like HTTP API endpoints to create and read mappings 
from CHRIS and CAMSIS identifiers to CRSids,
so that client applications can reliably submit 
and retrieve identifier mappings using a consistent, documented JSON API.

Background

The identifier mapping model(s) have been defined in the Identifiers API Django app to represent mappings between:

  • CHRIS (staff number) → CRSid.
  • CAMSIS (USN) → CRSid.

The identity-lib provides the canonical identifier schemes and parsing utilities:

  • CHRIS staff number: IdentifierSchemes.STAFF_NUMBER.
  • CAMSIS USN: IdentifierSchemes.USN.
  • CRSid: IdentifierSchemes.CRSID / CRSID_SCHEME.
  • Identifier / IdentifierSchemes.from_string(...) are used to normalise and validate identifier values and schemes (e.g. lowercasing CRSids).

This issue focuses on implementing the REST API layer (URLs, views, serializers) over the existing mapping model(s) using Django REST Framework, without yet implementing the full permissions/authorisation model (which will be covered in separate issues). The primary outcomes of this issue must satisfy the epic acceptance criteria that:

  • A client can read CHRIS identifier mappings.
  • A client can read CAMSIS identifier mappings.
  • A client can submit mappings for CHRIS and CAMSIS identifiers to CRSIDs.

Acceptance Criteria

  • At least one POST endpoint is implemented (e.g. /api/v1/identifier-mappings/) that allows clients to create CHRIS→CRSid and CAMSIS→CRSid mappings using JSON payloads.
  • The POST request body accepts, at minimum:
    • source_scheme (string; must resolve to IdentifierSchemes.STAFF_NUMBER or IdentifierSchemes.USN).
    • source_value (string; CHRIS staff number or CAMSIS USN).
    • target_scheme (string; must resolve to IdentifierSchemes.CRSID).
    • target_value (string; CRSid).
  • The POST serializer uses identitylib.identifiers.Identifier and IdentifierSchemes.from_string(...) to:
    • Resolve and validate schemes.
    • Normalise identifier values, including lowercasing CRSids.
    • Reject malformed or invalid identifier values and schemes with 4xx responses.
  • POSTing a valid CHRIS→CRSid or CAMSIS→CRSid mapping:
    • Persists a record using the identifier mapping model(s) from the previous story.
    • Returns HTTP 201 Created with a JSON representation of the created mapping.
  • Uniqueness constraints defined at the model level are respected by the API:
    • If a duplicate mapping is submitted (e.g. same source_scheme, source_value, target_scheme), the API returns a suitable 4xx error (e.g. 400 Bad Request) with a clear validation error message rather than creating a second record.
  • At least one GET endpoint is implemented (e.g. /api/v1/identifier-mappings/) that allows clients to retrieve mappings using query parameters.
  • The GET endpoint supports, at minimum:
    • Lookup by source identifier:
      • source_scheme + source_value together return the mapping for a CHRIS or CAMSIS identifier if it exists.
    • Lookup by target identifier:
      • target_scheme + target_value together return zero or more mappings pointing to a given CRSid.
  • GET responses:
    • Use DRF pagination for list responses where multiple mappings are returned.
    • Return 200 OK with a JSON body that includes:
      • Source scheme/value.
      • Target scheme/value.
      • Creation and last-updated timestamps.
      • Any model identifiers (e.g. primary key) needed for debugging/admin use.
    • Return 404 Not Found when a specific mapping is requested and does not exist (where a non-list/lookup-by-PK endpoint is used).
  • A DRF serializer class (or classes) is implemented for the mapping model(s) that:
    • Encapsulates identifier validation and normalisation logic.
    • Ensures that only supported source schemes (STAFF_NUMBER, USN) and target scheme (CRSID) are accepted.
    • Produces a consistent JSON representation used by both POST and GET.
  • URL patterns are added to the Django project for these endpoints under a versioned API namespace (e.g. /api/v1/), following the existing webapp boilerplate conventions.
  • Basic permission behaviour is enforced:
    • Endpoints are not publicly accessible (e.g. require DRF IsAuthenticated or equivalent).
    • Permission classes are structured so that a later story can replace or extend them with Apigee/Gateway-based authorisation without changing the API surface.
  • Unit tests are added that cover, at minimum:
    • Successful POST of a CHRIS→CRSid mapping.
    • Successful POST of a CAMSIS→CRSid mapping.
    • Rejection of invalid schemes / malformed identifiers on POST.
    • Handling of duplicate mapping submissions (ensuring appropriate 4xx response).
    • Successful GET lookup by CHRIS identifier.
    • Successful GET lookup by CAMSIS identifier.
    • Successful GET listing of mappings for a given CRSid.
  • The Identifiers API documentation is updated to:
    • Describe the new endpoints, their URLs, and HTTP methods.
    • Show example request/response payloads for CHRIS and CAMSIS mapping flows.
    • Explain which identifier schemes are currently supported and how they are validated using identity-lib.
Edited by Eugene E.