Master Data สอศ.

API reference

Read-only reference data for OVEC (geography, colleges, organizations, curricula, and general codes). Call this API instead of copying tables into your own database.

Sign in

Overview

The base URL in development is http://localhost:4000. Data is served over two transports that share one service layer, so they always agree on what is allowed:

  • GraphQL at POST /graphql — the full interface, including the only way to write data.
  • REST at GET /api/v1/… — a thin read-only wrapper for systems that cannot call GraphQL.

GraphiQL is available at http://localhost:4000/graphql during development.

Authentication

External systems authenticate with an API key sent in the Authorization header. API keys can read but never write — the only mutation path is a logged-in admin user.

Authorization: Bearer <api-key>

When PUBLIC_READ=true is set, data can be read without any key. Mutations always require a logged-in admin user regardless of this setting.

CallerReadWrite
AnonymousNo (unless PUBLIC_READ=true)No
API keyYesNo
User — VIEWERYesNo
User — EDITORYesYes
User — ADMINYesYes + manage API keys

REST (read-only)

Two routes per resource — list all, or fetch one by its natural code:

GET /api/v1/<resource>          # list
GET /api/v1/<resource>/{code}   # one record by code
GET /api/v1                     # index of all resources

List endpoints accept these query parameters:

search      text matched against the searchable fields
isActive    true | false
limit       page size (default 50, max 200)
offset      rows to skip
orderBy     a field name
order       asc | desc
<fkId>      filter by any declared foreign key, e.g. ?provinceId=<id>

Example requests:

curl -H "Authorization: Bearer $API_KEY" \
  "http://localhost:4000/api/v1/colleges?provinceId=<id>&limit=20"

curl -H "Authorization: Bearer $API_KEY" \
  "http://localhost:4000/api/v1/colleges/1350016101"

Responses are wrapped in data (the record or array) plus meta with pagination for list calls:

{
  "data": [ { "code": "1350016101", "nameTh": "…", "…": "…" } ],
  "meta": { "totalCount": 1234, "limit": 20, "offset": 0, "hasNextPage": true }
}

Writing is intentionally not exposed over REST — there is exactly one write path, which is easier to audit.

GraphQL

Every resource exposes the same set of operations, generated from one registry. Replace <plural>, <single> and <X> with the resource names in the table below:

# read
<plural>(filter, limit, offset, orderBy, includeDeleted): <X>Page!
<single>(id | code): <X>

# write (logged-in admin only)
create<X>(input: <X>CreateInput!): <X>!
update<X>(id: ID!, input: <X>UpdateInput!): <X>!
delete<X>(id: ID!): <X>!     # soft delete
restore<X>(id: ID!): <X>!

List query example with nested relations:

query {
  colleges(filter: { provinceId: "..." }, limit: 20) {
    totalCount
    items {
      code
      nameTh
      collegeType { nameTh shortName }
      subdistrict { nameTh district { nameTh province { nameTh } } }
    }
  }
}

The filter input also accepts search, isActive, and any declared foreign key. Each record exposes its relations both as the resolved object and as the raw …Id field.

Create an API key for an external system (admin only):

mutation {
  createApiKey(name: "student-registry") {
    token   # shown once — the server stores only a hash
    info { prefix scopes }
  }
}

Resources

Static list. Set PUBLIC_READ=true or sign in to fetch it live from the API. The same table is available at runtime via the entityDefinitions GraphQL query.

ResourceGraphQLREST path
Geographic regiongeoRegions / geoRegion/api/v1/geo-regions
Provinceprovinces / province/api/v1/provinces
Districtdistricts / district/api/v1/districts
Subdistrictsubdistricts / subdistrict/api/v1/subdistricts
OVEC regionovecRegions / ovecRegion/api/v1/ovec-regions
Organizationorganizations / organization/api/v1/organizations
College typecollegeTypes / collegeType/api/v1/college-types
Collegecolleges / college/api/v1/colleges
Education leveleducationLevels / educationLevel/api/v1/education-levels
Curriculumcurriculums / curriculum/api/v1/curriculums
Program typeprogramTypes / programType/api/v1/program-types
Program branchprogramBranches / programBranch/api/v1/program-branches
Program majorprogramMajors / programMajor/api/v1/program-majors
Code setcodeSets / codeSet/api/v1/code-sets
Code valuecodeValues / codeValue/api/v1/code-values