Skip to main content
A Provider calls one address per school with an HTTPS GET. ClassAtlas always answers with XML and HTTP 200, and the outcome is the code of the status element. The protocol began as iPay’s specification (payment-gateway.doc, version 1.03) and is now the one every Provider uses (ADR 0074). This page records how ClassAtlas implements it.

Endpoint

The examples on this page use iPay’s address. TBC Pay sends exactly the same requests to its own.
Planned (CA-1147): TBC Pay’s address does not answer yet.

Checks, in order

Every request passes these checks in this order. The first one that fails decides the answer. The IP check runs before the school is resolved, so a stranger never opens a school’s database or uses up its rate limit. Authentication runs after, because each school’s credentials live in its own database (ADR 0029).
Any unexpected error on this route is answered with code 99, never with an HTML error page.

Authentication

IP allow-list

Only the Providers’ servers are accepted. A Provider gives ClassAtlas the addresses it calls from, and one list serves every school and every Provider.
  • The check uses the address the connection came from, not X-Forwarded-For, which any caller can forge (ADR 0028).
  • An address on the list still needs that Provider’s credentials and secret key at the school.

Credentials

Each school has its own USERNAME, PASSWORD and secret key at each Provider, stored encrypted in the school’s database. The username and the password are both compared before answering, in constant time, so a wrong username and a wrong password take the same time.

HASH_CODE

HASH_CODE is the MD5 of every parameter value, in the order the parameters arrive, followed by the school’s secret key, in uppercase hex.
  • HASH_CODE itself is left out, wherever it appears in the request.
  • Values are taken URL-decoded and joined with no separator.
  • The order is the order of arrival, not a fixed list. If a Provider adds a parameter, the hash still validates (ADR 0026).
Example for pay, with test values and the secret key DemoSecretKey123:
Whether a Provider hashes the decoded or the raw value is unconfirmed. It only matters for EXTRA_INFO, the one parameter that could carry characters needing encoding, and iPay has confirmed it sends nothing there. A Provider’s test run against a school before go-live settles it.

Parameters

A parameter is required in the operations listed, unless marked optional. The upper limit on PAY_AMOUNT is the largest amount a transaction can hold.

Responses

Every response is one pay-response document: a status with a code and a text, a timestamp in Unix seconds, and the operation’s result when it succeeds. A refusal also carries retry.
Refusal
retry is false except when the school’s rate limit was hit. Telling a Provider a refused payment may be retried when it may not is how a double payment happens.

Operations

debt

Returns what the student owes and what it is made of.
Request
Response
debt is the student’s charges less their balance, never below zero, in tetri. It is read from the same balance view the ClassAtlas panel uses, so the bank and the school always see the same number. additional-info is what the payer reads. The values carry the whole line, and the names are only keys, because the specification does not say whether a Provider displays the names. The text is always in Georgian, whatever the application’s language. While the student owes, balance is the credit already counted against the charges, so the charges less the balance equal debt. When they owe nothing it is their credit, so a parent can tell “we are square” from “the school does not know my child”.

verify

Answers whether a payment may go ahead. It records nothing, because in the teller flow it is sent before the customer has handed over any money. It refuses only a student who has left the school and owes nothing (code 9). There is no upper limit on the amount: a parent may pay more than they owe.
Response

pay

Records the payment and returns its receipt number.
Request
Response
  1. The verify check runs again, because a teller’s order can be paid long after it was created.
  2. One transaction is written for the student. receipt-id is its ID in ClassAtlas.
  3. Everything else, from paying off charges to messaging the family, follows from that transaction. See How ClassAtlas records a Lookup payment.
A PAYMENT_ID is recorded once per Provider and channel. The same ID arriving again on the same channel is answered with code 8 and records nothing. A retry after a lost response therefore gets code 8, not the original receipt-id. iPay has confirmed that codes 8 and 18 mean the same thing to them. There is no operation to cancel a payment.

ping

Answers whether the school can take payments right now. It passes every authentication check, then reads the student balance view that every money operation depends on.
Request
A broken database answers code 99, which the Provider alerts on. A paused or unconfigured school answers code 1.

Status codes

Parameter errors are reported in a fixed order: a missing parameter (4), then an unknown service (10), then an amount out of range (7), then any other bad value (5). Code 18 exists in the specification, but ClassAtlas never sends it.