Master Data สอศ.
Read-only reference data for OVEC (geography, colleges, organizations, curricula, and general codes). Call this API instead of copying tables into your own database.
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:
POST /graphql — the full interface, including the only way to write data.GET /api/v1/… — a thin read-only wrapper for systems that cannot call GraphQL.GraphiQL is available at http://localhost:4000/graphql during development.
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.
| Caller | Read | Write |
|---|---|---|
| Anonymous | No (unless PUBLIC_READ=true) | No |
| API key | Yes | No |
| User — VIEWER | Yes | No |
| User — EDITOR | Yes | Yes |
| User — ADMIN | Yes | Yes + manage API keys |
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 resourcesList 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.
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 }
}
}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.
| Resource | GraphQL | REST path |
|---|---|---|
| Geographic region | geoRegions / geoRegion | /api/v1/geo-regions |
| Province | provinces / province | /api/v1/provinces |
| District | districts / district | /api/v1/districts |
| Subdistrict | subdistricts / subdistrict | /api/v1/subdistricts |
| OVEC region | ovecRegions / ovecRegion | /api/v1/ovec-regions |
| Organization | organizations / organization | /api/v1/organizations |
| College type | collegeTypes / collegeType | /api/v1/college-types |
| College | colleges / college | /api/v1/colleges |
| Education level | educationLevels / educationLevel | /api/v1/education-levels |
| Curriculum | curriculums / curriculum | /api/v1/curriculums |
| Program type | programTypes / programType | /api/v1/program-types |
| Program branch | programBranches / programBranch | /api/v1/program-branches |
| Program major | programMajors / programMajor | /api/v1/program-majors |
| Code set | codeSets / codeSet | /api/v1/code-sets |
| Code value | codeValues / codeValue | /api/v1/code-values |