ADAM

API Access to ADAM

Introduction the ADAM API

An API allows for another computer program to connect to ADAM to either access data stored in its database or to make changes to that data. ADAM makes use of a “RESTful” API and returns data mostly in JSON format.

What is a RESTful system?

REST is a technique of communicating with an API which is very common amongst web-based applications - such as ADAM. Other programs will make one of four types of web request depending on what they are hoping to do in the database, and include the necessary information for ADAM. ADAM then responds to that request with the appropriate data or success code.

How does access control work?

Access to the ADAM database is controlled using a token system. These are essentially random passwords that are created which are shared only with the other program that wishes to access the API. Because these tokens are really only meant to be used by a computer, it is not important that they are memorable or easy to type. In fact, ADAM will generate a random set of characters to be used as the API key and you are strongly encouraged to make use of the suggested token.

It is vitally important that the token is kept confidential between the person issuing it and the person using it. Anyone who knows the token will be able to access the API. Please read the Best Practices section below for further information.

Each API token can be given access to one or more API resources. Anyone who knows the API token can access all the resources that have been allocated to that token.

API tokens can be revoked at any point and can have their resources changed and added to over time. Any changes you make to the token and its API resource assignments will take place immediately.

Managing API Tokens in ADAM

In ADAM: Navigate to Administration → Security Administration → Manage API Tokens.

A list of existing API tokens will be shown. Click on Add new API Token to begin the process of creating a new Token.

  1. A random 30-character token will be generated. This should be left unmodified unless you have a very specific reason to do so. Once set, token values cannot be changed. If you need to change the token, you must delete the existing endpoint and create a new one.
  2. Select the appropriate resources to allow the token to access. Hold down the “Ctrl” key on your keyboard to allow you to select multiple resources by then clicking on those resources while holding down that button.
  3. Add notes if required. It is a good idea to make note of what service is making use of the API token.
  4. Click on Save Token.

A:\Users\Philip\AppData\Local\Microsoft\Windows\INetCache\Content.Word\big_warning_11.pngThe random 30 character token must be kept secret since will will allow anyone who knows it access to the data stored in the ADAM database. It will need to be shared with the integration provider and great care should be taken with how they are provided the API key. We strongly recommend against sending this information via email or other unsecured means.

Managing Existing Tokens

In the table of existing API tokens, you have the option to edit, delete or regenerate the API token.

Edit allows you to change the Resources and Notes associated with an endpoint, but does not allow you to edit the Token.

Regenerating a token will create a new random value for the token but will keep your resources and notes the same. If you do regenerate a token, please remember to update your external systems with the new token.

Deleting the token will remove it from the list and it will no longer be available for use. Systems that rely on the resources will no longer have access to the data supplied by ADAM.

Best Practice Security Principals

The following are provided as best practice guidelines for managing API tokens.

  1. Treat API Tokens as top secret. Do not send them via email and do not publish them in a place where they could be accessed by unauthorized personnel. API access can expose sensitive data. Allowing an API tokens to fall into the wrong hands could expose personal information about the users of your system and this would be considered an offence under the “Protection of Personal Information Act” (POPIA). Access to such personal information could become a security and safety issue.
  2. Each entity (e.g. a program that is accessing data from ADAM) should have its own token or tokens. Tokens should never be shared between entities. If another entity requires access to the same data, give it a new token. This allows you to revoke each token individually and stop one program from accessing the data without affecting any other programs.
  3. Programmers integrating with the ADAM API should not, under any circumstances, include API tokens in their source code and should always fetch them from some form of access controlled data storage.

API Interactions

Authentication

All API requests should be authenticated using a Bearer Token.

Example:

Authenticating with the token value svyzBvkuuXLdJwV7YcdYsQFVX5ha54 would yield the following header:

Authorize: Bearer svyzBvkuuXLdJwV7YcdYsQFVX5ha54

ADAM also will accept a Basic Authorization header with an arbitrary username. Authenticating with the username apitoken token value svyzBvkuuXLdJwV7YcdYsQFVX5ha54 would yield the following header:

Authorize: Basic YXBpdG9rZW46c3Z5ekJ2a3V1WExkSndWN1ljZFlzUUZWWDVoYTU0

API Requests

All API requests, as listed below, should be prefixed with the “apicore” folder to make the URL end-point:

https://adam.example.com/apicore/

The remainder of the URL generally consists of a module name, a data set and zero or more parameters. For example:

https://demo.adam.co.za/apicore/apirequests/test/parameter

Parameters should be “percent encoded”. Spaces should be encoded as %20 and not as a “+”.

A GET request to this API end-point would require token access to the resource: APIRequests/test/get. Note that without specifically assigned access, access to the resource - even this test resource - will be denied.

API Responses

All responses will be returned within JSON objects. The basic structure of these objects is:

{

    "data": null,

    "message": "",

    "response": {

        "error": "",

        "code": 200

    }

}

Any response which does not have these properties as listed above, MUST be treated as invalid.

The contents of the data attribute will depend on the API endpoint being interrogated.

The message attribute contains a human-readable message which, in most cases, describes the data set that has been returned. This is intended for debugging and may change unpredictably with future versions of ADAM.

The response code should mirror the HTTP response code which will be descriptive of the success or failure of the call. The error attribute will provide a human-readable description of the error. The error message is not intended to be interpreted by machines.

API Resources

These are the available documented resources. Other resources are available but are not listed here until their development is complete and considered stable.

APIRequests/test/get

A test method to the API.

Request

GET /apicore/apirequests/test/[Parameter1]/[Parameter2]

Parameters

[Parameter1]: An arbitrary parameter that is returned.

[Parameter2]: An arbitrary parameter that is returned.

Output

The output data will be a JSON object containing attributes parameter1 and parameter2, both of which will contain the values provided in the request.

Example:

https://demo.adam.co.za/apicore/apirequests/test/First%20Parameter/Second

{

    "data": {

        "parameter1": "First Parameter",

        "parameter2": "Second"

    },

    "message": "Hello, you're speaking to Random High School's ADAM. We are currently on revision 6125 and the local time is 11:26:46.",

    "response": {

        "error": "OK",

        "code": 200

    }

}

AbsenteeKiosk/register/post

This registers a pupil as either present or late. It is intended to be used either by automated access control systems or ADAM’s own absentee kiosk.

Request

Parameters

Response

If the pupil identifier can be matched against an existing pupil, the endpoint will return two items in the data object. These are used internally by ADAM’s “Absentee Kiosk” feature.

The times and windows are configured in ADAM’s site settings. Depending on these settings, ADAM will report one of the following HTTP status codes:

In each case, the status code will be corroborated by a more descriptive message.

Example:

{

    "data": {

        "message": "<strong>Joe Smith</strong> has been recorded as <strong>present</strong>",

        "colour": "green"

    },

    "message": "",

    "response": {

        "error": "Present",

        "code": 200

    }

}

Absentees/summarycount/get

Returns a list of pupils and the number of days they’ve been absent. This counts all the absentees with a reason that is set to count as “absent”. Only pupils with absentee records are returned. All pupils, including those that might have left the school, are returned.

Request

GET to /apicore/absentees/summarycount/<from>[/<to>]

Parameters

Response

The data attribute will be an array of zero or more JSON objects.

Example:

GET /apicore/absentees/summarycount/2018-01-01/2018-01-31

{

    "data": [

        {

            "pupil_id": 875,

            "pupil_admin": "19634",

            "absent_count": 1

        },

        {

            "pupil_id": 879,

            "pupil_admin": "52351",

            "absent_count": 2

        }

    ],

    "message": "Absentee counts for all pupils from 2018-01-01 to 2018-01-31.",

    "response": {

        "error": "OK",

        "code": 200

    }

}

Absentees/list/get

Gets a list of pupils absent with the reasons.

Request

GET to /apicore/absentees/list/[<date>[/<to>]]

Parameters

Response

GET /apicore/absentees/list/2018-01-30

{

    "data": [

        {

            "pupil_id": 1720,

            "pupil_admin": "47547",

            "absent_date": "2018-01-31",

            "absent_reason_id": 1,

            "absent_reason_description": "Absent",

            "absent_notes": "App Test"

        }

    ],

    "message": "Absentee list for all pupils from 2018-01-31 to 2018-01-31.",

    "response": {

        "error": "OK",

        "code": 200

    }

}

The data attribute contains an array of zero or more absentee records. Each record is a JSON object with the following properties:

Applications/applicationformfields/get

The ability to see which fields are accepted as part of the application form. These fields can be customised by updating the core and custom fields to change their availability in the application form.

Request

GET request to /apicore/applications/applicationformfields

Parameters

None

Response

The output data will be a JSON object containing the fields that are accepted. Within the data property are two sub arrays for families and pupils. These list the field names that are accepted.

Example:

https://demo.adam.co.za/apicore/applications/applicationformfields

{

    "data": {

        "families": [

            "family_primary_idnum",

            "family_primary_lastname",

            "family_primary_firstname",

            "family_primary_fullfirst",

            "family_primary_title",

            "family_primary_initials",

            "family_primary_gender",

            "family_primary_birth",

            "family_primary_occupation",

            "family_primary_employer",

            "family_primary_workphone",

            "family_primary_cell",

            "family_primary_cell_sms",

            "family_primary_email",

            "family_secondary_idnum",

            "family_secondary_lastname",

            "family_secondary_firstname",

            "family_secondary_fullfirst",

            "family_secondary_title",

            "family_secondary_initials",

            "family_secondary_gender",

            "family_secondary_birth",

            "family_secondary_occupation",

            "family_secondary_employer",

            "family_secondary_workphone",

            "family_secondary_cell",

            "family_secondary_cell_sms",

            "family_secondary_email",

            "family_address_residential_1",

            "family_address_residential_2",

            "family_address_residential_suburb",

            "family_address_residential_city",

            "family_address_residential_province",

            "family_address_residential_code",

            "family_address_residential_country",

            "family_address_postal_1",

            "family_address_postal_2",

            "family_address_postal_suburb",

            "family_address_postal_city",

            "family_address_postal_province",

            "family_address_postal_code",

            "family_address_postal_country",

            "family_home_phone",

            "family_home_fax",

            "family_ice",

            "family_ice_number",

            "family_report_required"

        ],

        "pupils": [

            "pupil_lastname",

            "pupil_fullfirst",

            "pupil_firstname",

            "pupil_gender",

            "pupil_idnumber",

            "pupil_birth",

            "pupil_religion",

            "pupil_population_id",

            "pupil_language_id",

            "pupil_language_other",

            "pupil_teaching_language_id",

            "pupil_entry",

            "pupil_final",

            "pupil_email",

            "pupil_cell",

            "pupil_cell_sms",

            "pupil_allergies",

            "pupil_medaid_name",

            "pupil_medaid_number",

            "pupil_medaid_principal",

            "pupil_medaid_principal_id",

            "pupil_doctor",

            "pupil_doctor_phone",

            "pupil_orphan_status",

            "pupil_relationships",

            "pupil_atschool",

            "pupil_prevschool_firstprovince",

            "pupil_prepschool",

            "pupil_prevschool_country",

            "pupil_prevschool_formalgrr",

            "pupil_nationality",

            "pupil_studypermit_required",

            "pupil_studypermit",

            "custom_38",

            "custom_36"

        ]

    },

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

Applications/apply/post

Submit an application to the site. Note that if the ID number submitted matches an existing parent, the child will automatically be linked to that parent. Note that when applications are submitted through ADAM’s web interface, ADAM automatically authenticates the parent to ensure that strange children are not linked to their profiles. Implicit in the web application is the validation of the email address which is done as part of the application process. Applications received via the API are not given such scrutiny and special care should be taken on the sending system to mitigate against spam and fraudulent attempts at applications.

Request

POST request to /apicore/applications/apply

Parameters

None - data sent by message body.

Body

The body of the request should contain the data required for the application. The data should either be in JSON format, or as an encoded query string (as is typical with normal form-submitted data).

Fields: The three fields, idnumber, email, and phone, may be duplicated within the parent information. It is not necessary that they complete them twice, but it is necessary for the information to be submitted both with the family and as separate information.

Note carefully the point about existing parents: if their ID or passport numbers already exist in ADAM’s database, the family information provided in the application will be silently discarded in favour of information already in the database. Thus having updated contact information provided in the email and phone fields is important. The silent discarding is to ensure that malicious actors cannot update family information without their authorisation.

A minimum set of required fields is:

Example (JSON):

{

  "idnumber": "1234567890123",

  "email": "morticia@adam.co.za",

  "phone": "0834699569",

  "application": {

    "pupil": [

      {

        "pupil_lastname": "Addams",

        "pupil_firstname": "Wednesday",

        "pupil_fullfirst": "Wednesday Jane",

        "pupil_gender": "Female",

        "entry_year": "2019",

        "entry_month": "1",

        "entry_grade": "10",

        "relationship": [{

          "primary": "biological",

          "secondary": "step parent"

        }]

      },

      {

        "pupil_lastname": "Addams",

        "pupil_firstname": "Pugsley",

        "pupil_fullfirst": "Pugsley George",

        "pupil_gender": "Male",

        "entry_year": "2019",

        "entry_month": "1",

        "entry_grade": "8",

        "relationship": [{

          "primary": "step parent",

          "secondary": "biological"

        }]

      }

    ],

    "family": {

      "family_primary_idnum": "1234567890123",

      "family_primary_lastname": "Addams",

      "family_primary_firstname": "Gomez",

      "family_primary_fullfirst": "Gomez",

      "family_secondary_idnum": "1234567890123",

      "family_secondary_lastname": "Addams",

      "family_secondary_firstname": "Morticia",

      "family_secondary_fullfirst": "Morticia May"

    },

    "email": [

      {

        "member": "primary",

        "address": "gomes@adam.co.za",

        "bulk": "Yes",

        "reports": "Yes"

      },

      {

        "member": "secondary",

        "address": "morticia@adam.co.za",

        "bulk": "Yes",

        "reports": "Yes"

      }

    ]

  }

}

Example (URL Encoded):

idnumber=1234567890123&email=morticia%40adam.co.za&phone=0834699569&application%5Bpupil%5D%5B0%5D%5Bpupil_lastname%5D=Addams&application%5Bpupil%5D%5B0%5D%5Bpupil_firstname%5D=Wednesday&application%5Bpupil%5D%5B0%5D%5Bpupil_fullfirst%5D=Wednesday+Jane&application%5Bpupil%5D%5B0%5D%5Bpupil_gender%5D=Female&application%5Bpupil%5D%5B0%5D%5Bentry_year%5D=2019&application%5Bpupil%5D%5B0%5D%5Bentry_month%5D=1&application%5Bpupil%5D%5B0%5D%5Bentry_grade%5D=10&application%5Bpupil%5D%5B0%5D%5Brelationship%5D%5B0%5D%5Bprimary%5D=biological&application%5Bpupil%5D%5B0%5D%5Brelationship%5D%5B0%5D%5Bsecondary%5D=step+parent&application%5Bpupil%5D%5B1%5D%5Bpupil_lastname%5D=Addams&application%5Bpupil%5D%5B1%5D%5Bpupil_firstname%5D=Pugsley&application%5Bpupil%5D%5B1%5D%5Bpupil_fullfirst%5D=Pugsley+George&application%5Bpupil%5D%5B1%5D%5Bpupil_gender%5D=Male&application%5Bpupil%5D%5B1%5D%5Bentry_year%5D=2019&application%5Bpupil%5D%5B1%5D%5Bentry_month%5D=1&application%5Bpupil%5D%5B1%5D%5Bentry_grade%5D=8&application%5Bpupil%5D%5B1%5D%5Brelationship%5D%5B0%5D%5Bprimary%5D=step+parent&application%5Bpupil%5D%5B1%5D%5Brelationship%5D%5B0%5D%5Bsecondary%5D=biological&application%5Bfamily%5D%5Bfamily_primary_idnum%5D=1234567890123&application%5Bfamily%5D%5Bfamily_primary_lastname%5D=Addams&application%5Bfamily%5D%5Bfamily_primary_firstname%5D=Gomez&application%5Bfamily%5D%5Bfamily_primary_fullfirst%5D=Gomez&application%5Bfamily%5D%5Bfamily_secondary_idnum%5D=1234567890123&application%5Bfamily%5D%5Bfamily_secondary_lastname%5D=Addams&application%5Bfamily%5D%5Bfamily_secondary_firstname%5D=Morticia&application%5Bfamily%5D%5Bfamily_secondary_fullfirst%5D=Morticia+May&application%5Bemail%5D%5B0%5D%5Bmember%5D=primary&application%5Bemail%5D%5B0%5D%5Baddress%5D=gomes%40adam.co.za&application%5Bemail%5D%5B0%5D%5Bbulk%5D=Yes&application%5Bemail%5D%5B0%5D%5Breports%5D=Yes&application%5Bemail%5D%5B1%5D%5Bmember%5D=secondary&application%5Bemail%5D%5B1%5D%5Baddress%5D=morticia%40adam.co.za&application%5Bemail%5D%5B1%5D%5Bbulk%5D=Yes&application%5Bemail%5D%5B1%5D%5Breports%5D=Yes

Response

A simple object providing notification of success or failure. The application field gives a code unique to this application which will, in a future development, allow for editing of the application.

{

    "data": {

        "application": "6ESKmQYMWH3KbJUdAESsZUi3BysaLx"

    },

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

ClassReg/grade/get

Returns a list of classes that a grade of pupils is registered for.

Request

GET /apicore/classreg/grade/<grade>

Parameters

Response

The response is an array of pupil registration objects, each following the structure below:

{

    "data": [

        {

            "registration_id": 162555,

            "pupil_id": 1234,

            "pupil_lastname": "Last-Name",

            "pupil_firstname": "First",

            "class_id": 4231,

            "class_description": "Z",

            "class_gradeyear": "11",

            "subject_id": 101,

            "subject_name": "English Home Language",

            "subject_short": "Eng",

            "category_id": 1,

            "category_description": "Academic",

            "registration_datestart": "2024-01-20",

            "registration_dateend": null,

            "staff_id": 123,

            "staff_firstname": "Educator",

            "staff_lastname": "Mary"

        }

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

DataQuery/get/get

Provides automated access to a whole-school scratch list. The contents of the scratch list fields can be customised as per the settings in ADAM found at Administration → Security → Manage Data Query API Fields.

Please treat this feature with the utmost care. By its very definition, it gives wide access to a range of personal data.

Create a Data Query Secret

In order to use this API endpoint, an additional data query token must be defined.

Note that field access definitions can only be linked to a single API Token. If multiple API tokens require access to the same fields, this process must be duplicated for each API token and a unique list created for each.

Click on Add record when done.

A second screen will show, allowing you to select the fields required for this query:

Check the fields that you require and save your selections using the button at the bottom.

Request

GET /apicore/dataquery/get/<secret>

OR, for a modified data structure to provide more consistency for automated systems, (see example response below), add the version parameter “2” to the end of the request.

GET /apicore/dataquery/get/<secret>/2

Parameters

Response

GET /apicore/dataquery/get/GXiE4V5qYB

{

    "data": {

        "49": {

            "admin_number_1": "3316",

            "lurits_number_177": "",

            "age_6": "15 years, 200 days",

            "gender_10": "Male"

        },

        "4688": {

            "admin_number_1": "6333",

            "lurits_number_177": "",

            "age_6": "17 years, 10 days",

            "gender_10": "Male"

        }

    },

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

The data attribute is a JSON object with zero or more attributes, each being the ID of the relevant data object as specified in the Data Query setup. Each of these objects will have a number of attributes depending on the fields chosen. Note that the names of these attributes can be overridden by the school. However, there is a unique numeric identifier that is appended to each which will remain constant. Logic should be based around that identifier. Note that custom fields will contain the word “custom” before the unique identifier and so that should also be checked for.

GET /apicore/dataquery/get/GXiE4V5qYB/2

Where the optional parameter “2” is included at the end, the structure of the returned data will change. An additional “fields” property is included with clearer textual descriptions of the fields. The fields in each of the data objects is identified by the immutable identifier. This allows automated systems to ignore parts of the field name that might change.

{

    "fields": [

        {

           "id": 1,

           "name": "Admin Number"

        },

        {

           "id": 177,

           "name": "LURITS Number"

        },

        {

           "id": 6,

           "name": "Age"

        },

        {

           "id": 10,

           "name": "Gender"

        }  

    ],

    "data": {

        "49": {

            "1": "3316",

            "177": "",

            "6": "15 years, 200 days",

            "10": "Male"

        },

        "4688": {

            "1": "6333",

            "177": "",

            "6": "17 years, 10 days",

            "10": "Male"

        }

    },

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

DataQuery/getsince/get

See above.

Request

GET /apicore/dataquery/getsince/<secret>/<timestamp>[/<version>]

Parameters

Response

See above.

DataQuery/getone/get

See above.

Request

GET /apicore/dataquery/getone/<secret>/<identifier>[/<version>]

Parameters

Response

See above.

Export/families/get

Allows family information to be extracted easily.

Request

GET /apicore/export/families

GET /apicore/export/families/all

GET /apicore/export/families/current

GET /apicore/export/families?updated_since=2024-10-01+08:15:30

GET /apicore/export/families/all?updated_since=2024-10-01+08:15:30

GET /apicore/export/families/current?updated_since=2024-10-01+08:15:30

Parameters

The last parameter (all or current) may be omitted - the default setting is to return current families only. The structure of the data is unchanged.

An optional parameter, updated_since, will only return changes that have been made on or after the time specified. Any valid timestamp, that is URL encoded, can be used.

Note well that changes to email addresses are not reflected in the modified time.

Response

Valid responses will contain an array of family objects in the data property. The family_primary_email and family_secondary_email will be arrays of email addresses:

{

    "data": [

        {

            "family_id": 531,

            "family_admin": "0",

            "family_primary_lastname": "Adamson",

            "family_primary_firstname": "Adam",

            "family_primary_title": "Mr",

            "family_primary_idnum": "1234567890123",

            "family_primary_occupation": "Businessman",

            "family_primary_employer": "ADAM EduTech",

            "family_primary_workphone": "0615096077",

            "family_primary_cell": "0615096077",

            "family_secondary_lastname": "",

            "family_secondary_firstname": "",

            "family_secondary_idnum": "",

            "family_secondary_occupation": "",

            "family_secondary_employer": "",

            "family_secondary_workphone": "",

            "family_secondary_cell": "",

            "family_address_postal_1": "18 Lello Road",

            "family_address_postal_2": "",

            "family_address_postal_suburb": "Assagay",

            "family_address_postal_city": "Outer West Durban",

            "family_address_postal_province": "KwaZulu-Natal",

            "family_address_postal_code": "3600",

            "family_address_postal_country": "South Africa",

            "family_address_residential_1": "18 Lello Road",

            "family_address_residential_2": "",

            "family_address_residential_suburb": "Assagay",

            "family_address_residential_city": "Outer West Durban",

            "family_address_residential_province": "KwaZulu-Natal",

            "family_address_residential_code": "3610",

            "family_address_residential_country": "South Africa",

            "family_notes": "",

            "family_modify": "2024-09-18 08:37:41",

            "family_primary_email": [

                "testing+primary@testing.adam.co.za",

                "testing+primary2@testing.adam.co.za"

            ],

            "family_secondary_email": [

            ]

        }

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

ExternalAuth/auth/post

Allows ADAM to be used as an external authentication source.

Note well: This API endpoint will divulge user information for a valid login name. As with any API key, it is imperative that it is kept secret and changed if a breach is suspected.

Request

POST /apicore/externalauth/auth/

Parameters

These parameters are sent via form-data parameters.

Response

Integrating systems should check the HTTP response code rather than the presence of user information in the data object.

If a valid username and password are supplied, the HTTP response code will be 200. The data object contains the user information and the contained response code will be 200:

{

    "data": {

        "username": "admin",

        "firstname": "Patrick",

        "lastname": "Cloete",

        "email": "testing+staff_1@adam.co.za",

        "type": "staff",

        "id": "1"

    },

    "message": "",

    "response": {

        "error": "Login successful",

        "code": 200

    }

}

If a valid username is supplied, but the password is incorrect, the HTTP response code will be 401. The data object will contain user information and the contained response code will be 401:

{

    "data": {

        "username": "admin",

        "firstname": "Patrick",

        "lastname": "Cloete",

        "email": "testing+staff_1@adam.co.za",

        "type": "staff",

        "id": "1"

    },

    "message": "",

    "response": {

        "error": "Username or password not recognised",

        "code": 401

    }

}

If an invalid username is supplied, the HTTP response code will be 401. The data object will be empty and the contained response code will be 401.

{

    "data": [],

    "message": "",

    "response": {

        "error": "Username or password not recognised",

        "code": 401

    }

}

Pupils/image/get

Returns an image of a pupil.

Request

GET /apicore/pupils/image/<pupil_id>

Parameters

Response

GET /apicore/reporting/pupils/image/123

Unlike other API calls, this will return an image file and not a JSON object. The image type will be specified by the response’s Content-Type header, but will almost certainly be a JPG image. A response code of 404 suggests that the image does not exist.

Families/currentchildren/get

Request

GET /apicore/families/currentchildren/<family_id>

Parameters

Response

This query returns an array of pupils. If no pupils are attached to the family, or if the family identifier does not exist, then the response will be returned with a “404” HTTP status code.

{

    "data": [

        "49",

        "4688"

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

Families/searchbyid/get

Request

GET /apicore/families/searchbyid/<RSA_ID_Number>

Parameters

Response

This response returns an array of generally one family identifier, but if an ID number is associated with many parents, all will be returned in the array. This is discouraged in the interface, but schools may still do this.

Where the ID number cannot be found, a response will be returned with an HTTP 404 status code.

{

    "data": [

        "1234"

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

FamilyRelationships/family/get

Gets a list of current pupils linked to a family with their relationships descriptors for primary and secondary parents.

Request

GET /apicore/familyrelationships/family[/<family_id>]

Parameters

Response

GET /apicore/familyrelationships/family/123

{

    "data": [

        "111": {

            "primary": "biological",

            "secondary": "step parent"

        },

        "321": {

            "primary": "step parent",

            "secondary": "biological"

        }

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

The data attribute contains an array of 0 or more objects.

Possible values include:

GET /apicore/familyrelationships/family

{

    "data": [

        "123": {

            "111": {

                "primary": "biological",

                "secondary": "step parent"

            },

            "321": {

                "primary": "step parent",

                "secondary": "biological"

            }

        },

        …

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

FamilyRelationships/pupil/get

Gets a list of families linked to a pupil with their relationships descriptors for primary and secondary parents.

Request

GET /apicore/familyrelationships/pupil[/<pupil_id>]

Parameters

Response

GET /apicore/familyrelationships/pupil/123

{

    "data": [

        "111": {

            "primary": "biological",

            "secondary": "step parent"

        },

        "321": {

            "primary": "step parent",

            "secondary": "biological"

        }

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

The data attribute contains an array of 0 or more objects.

Possible values include:

GET /apicore/familyrelationships/pupil

{

    "data": [

        "123": {

            "111": {

                "primary": "biological",

                "secondary": "step parent"

            },

            "321": {

                "primary": "step parent",

                "secondary": "biological"

            }

        },

        …

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

Leaves/approved/get

Gets a list of approved leaves with an end date that is either today or in the future.

Request

GET /apicore/leaves/approved/<pupil>

Parameters

Response

GET /apicore/leaves/approved/6050

{

    "data": [

        {

            "leave_request_id": 4765,

            "leave_request_out": "2024-10-18 14:15:00",

            "leave_request_in": "2024-10-20 18:30:00",

            "leave_request_destination": "Home",

            "leave_request_host": "Parents",

            "leave_request_host_contact": "083",

            "leave_request_notes": "thanks",

            "leave_request_approval_notes": "\n",

            "leave_request_status": "Approved",

            "leave_request_user_id": 1,

            "leave_request_user_type": "staff",

            "leave_request_submitted_datetime": "2024-10-15 10:37:01",

            "leave_request_reminder_datetime": null,

            "leave_request_choices": "Will he need Saturday Lunch:No\nWill he need Sunday Supper:No\nDo you need a gate code:No\n",

            "leave_type_id": 1,

            "leave_type_description": "Full Weekend Leave",

            "leave_type_overnight": "Yes",

            "leave_type_off_campus": "Yes"

        }

    ],

    "message": "Leaves for Joseph Tshabalala",

    "response": {

        "error": "OK",

        "code": 200

    }

}

The data attribute contains an array of 0 or more leave records.

Reporting/periods/get

Gets a list of reporting periods for a year.

Request

GET /apicore/reporting/periods[/<year>]

Parameters

Response

GET /apicore/reporting/periods/2018

{

    "data": [

        {

            "period_id": "31",

            "period_name": "Term 1",

            "period_start": "2018-01-01",

            "period_end": "2018-12-02",

            "period_publish": "2018-12-02 12:00:00"

        }

    ],

    "message": "Reporting periods from year 2018",

    "response": {

        "error": "OK",

        "code": 200

    }

}

The data attribute contains an array of 0 or more reporting period objects.

Reporting/results/get

Gets all academic results for a reporting period.

Request

GET to /apicore/reporting/results/<reportingperiod>

Parameters

Response

GET /apicore/reporting/results/31

 {

    "data": [

        {

            "pupil_id": 1754,

            "pupil_admin": "55012",

            "pupil_grade": 9,

            "results": [

                {

                    "subject_id": 1,

                    "subject_name": "English",

                    "dbe_subject_code": "",

                    "result_term": 50,

                    "result_ytd": 50

                },

                {

                    "subject_id": 40,

                    "subject_name": "Technology",

                    "dbe_subject_code": "15351142",

                    "result_term": null,

                    "result_ytd": null

                }

            ],

            "report_aggregate": 72.5,

            "report_aggregate_ytd": 72.5,

            "report_modified": "2016-02-11 11:36:17"

        }

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

The data attribute contains an array of 0 or more pupil objects. The pupil object has the following attributes:

Staff/image/get

Returns an image of a staff member.

Request

GET /apicore/staff/image/<staff_id>

Parameters

Response

GET /apicore/reporting/staff/image/123

Unlike other API calls, this will return an image file and not a JSON object. The image type will be specified by the response’s Content-Type header, but will almost certainly be a JPG image. A response code of 404 suggests that the image does not exist.

XDevMan/alumni/get

Returns a list of Alumni and their last-modified dates

Request

GET /apicore/xdevman/alumni/<year>

Parameters

Response

GET /apicore/xdevman/alumni/2019

{

    "data": [

        {

            "pupil_id": "2240",

            "pupil_admin": "7623",

            "pupil_modify": "2019-11-11 16:25:54",

            "alumni_modify": "2020-01-02 16:04:04"

        },

        {

            "pupil_id": "1319",

            "pupil_admin": "7289",

            "pupil_modify": "2019-11-11 16:25:54",

            "alumni_modify": "2020-01-02 16:04:04"

        }

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

In each record, the internal ID and school-provided administration number are returned. There are two modification times because data for alumni is stored in two separate places (one from the historical pupil information, and another from the alumni-specific information).

XDevMan/currentpupils/get

Returns a list of current pupils and their list of modification dates.

Request

GET /apicore/xdevman/currentpupils

Parameters

Response

GET /apicore/xdevman/currentpupils

{

    "data": [

        {

            "pupil_id": "2240",

            "pupil_admin": "7623",

            "pupil_modify": "2019-11-11 16:25:54"

        },

        {

            "pupil_id": "1319",

            "pupil_admin": "7289",

            "pupil_modify": "2019-11-11 16:25:54"

        }

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

In each record, the internal ID and school-provided administration number are returned. There are two modification times because data for alumni is stored in two separate places (one from the historical pupil information, and another from the alumni-specific information).

XDevMan/leavers/get

Returns a list of Leavers and their last-modified dates. A leaver for a year is a person who was deregistered during the course of that year. It includes people from all grades.

Request

GET /apicore/xdevman/leavers/<year>

Parameters

Response

GET /apicore/xdevman/leavers/2019

{

    "data": [

        {

            "pupil_id": "2240",

            "pupil_admin": "7623",

            "pupil_modify": "2019-11-11 16:25:54",

            "alumni_modify": "2020-01-02 16:04:04"

        },

        {

            "pupil_id": "1319",

            "pupil_admin": "7289",

            "pupil_modify": "2019-11-11 16:25:54",

            "alumni_modify": "2020-01-02 16:04:04"

        }

    ],

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

In each record, the internal ID and school-provided administration number are returned. There are two modification times because data for alumni is stored in two separate places (one from the historical pupil information, and another from the alumni-specific information).

XDevMan/alumnus/get

Returns the details of a single alumnus.

Request

GET /apicore/xdevman/alumnus/<pupil_id>

Parameters

Response

GET /apicore/xdevman/alumnus/999

{

    "data": {

        "pupil_id": "999",

        "pupil_admin": "6727",

        "pupil_lastname": "xxx",

        "pupil_firstname": "xxx",

        "pupil_fullfirst": "xxx",

        "pupil_birth": "1994-08-xx",

        "pupil_final": "2012",

        "pupil_gender": "Female",

        "pupil_entry": "2010-07-12",

        "pupil_exit": "2012-12-31",

        "pupil_idnumber": "9408xxx",

        "pupil_population_id": "4",

        "pupil_language_id": "2",

        "pupil_language_other": "",

        "pupil_email": "",

        "pupil_email_personal": "",

        "pupil_prepschool": "xxx",

        "pupil_nationality": "South Africa",

        "pupil_boarder": "3",

        "alumni_title": "Miss",

        "alumni_marital_status": "",

        "alumni_maiden_name": "",

        "alumni_spouse_title": "",

        "alumni_spouse_firstname": "",

        "alumni_spouse_gender": null,

        "alumni_spouse_occupation": "",

        "alumni_date_married": "0000-00-00",

        "alumni_region": "",

        "alumni_district": "",

        "alumni_branch_id": null,

        "alumni_type_id": "1",

        "alumni_deceased": "No",

        "alumni_deceased_date": null,

        "alumni_workphone": "",

        "alumni_homephone": "(031) xxx 6xxx",

        "alumni_other": "",

        "alumni_reason_left": "",

        "alumni_exit_grade": "12",

        "alumni_previous_school": null,

        "alumni_qualification": "Senior Certificate",

        "family": {

            "families": [

                {

                    "family_id": "873",

                    "family_admin": "0",

                    "family_primary_lastname": "xxx",

                    "family_primary_firstname": "xxx",

                    "family_primary_fullfirst": "xxx",

                    "family_primary_initials": "X",

                    "family_primary_title": "Mr",

                    "family_primary_idnum": "651xxxx",

                    "family_primary_gender": "Male",

                    "family_primary_occupation": "xxx",

                    "family_primary_employer": "xxx",

                    "family_primary_workphone": "0315xxx",

                    "family_primary_cell": "083xxx",

                    "family_primary_birth": "1965-10-xx",

                    "family_secondary_lastname": "xxx",

                    "family_secondary_firstname": "xxx",

                    "family_secondary_fullfirst": "xxx",

                    "family_secondary_initials": "X",

                    "family_secondary_title": "Mrs",

                    "family_secondary_idnum": "6607xxx",

                    "family_secondary_gender": "Female",

                    "family_secondary_occupation": "xxx",

                    "family_secondary_employer": "xxx",

                    "family_secondary_workphone": "0315xxx",

                    "family_secondary_cell": "083xxx",

                    "family_secondary_birth": "1966-07-xx",

                    "family_address_postal_1": "xxx",

                    "family_address_postal_2": "xxx",

                    "family_address_postal_suburb": "xxx",

                    "family_address_postal_city": "",

                    "family_address_postal_province": "",

                    "family_address_postal_code": "xxx",

                    "family_address_postal_country": "South Africa",

                    "family_address_residential_1": "xxx",

                    "family_address_residential_2": "xxx",

                    "family_address_residential_suburb": "xxx",

                    "family_address_residential_city": "",

                    "family_address_residential_province": "",

                    "family_address_residential_code": "",

                    "family_address_residential_country": "xxx",

                    "family_home_phone": "03150xxx",

                    "family_home_fax": "03150xxx"

                }

            ],

            "email": [

                {

                    "email_family_id": "873",

                    "email_member": "primary",

                    "email_address": "xxx@example.com"

                },

                {

                    "email_family_id": "873",

                    "email_member": "secondary",

                    "email_address": "yyy@example.com"

                }

            ]

        }

    },

    "message": "",

    "response": {

        "error": "OK",

        "code": 200

    }

}

A record of a single alumnus is returned.

Specific Integration Requirements

Please see the Third Party Integration section in this documentation.