HTTP REST API and PostgreSQL schemas built for TermBase eXchange (TBX) v3. The API currently supports the TBX-Basic dialect and Data Category as Attribute (DCA) style. The API and PostgreSQL schemas are part of the BaseTerm web application.
Before installing any instance of the BaseTerm API, please reach out to the BYU TRG at byutrg@gmail.com to establish a dialogue with the team. Please include any necessary contact info so that we can reach out to you for important version updates.
- PostgreSQL 14.x
- Node.js 16.x
- Python 3.9.x
A PostgreSQL (postgres) instance will be needed for the BaseTerm API application. A database will also need to be created in the postgres instance.
Please reference the postgres downloads for installers for various platforms.
The postgres database will need to be setup with proper schemas using the node-pg-migrate postgres migration tool. The tool first needs to be installed using NPM. Once installed, the tool is run with a connection string for the postgres database.
npm ci
DATABASE_URL=<postgres database connection string> npm run migrate up
Please reference the node-pg-migrate docs for further use of this migration tool.
- Rollbar logging token (optional). Please contact the BYU TRG team to obtain this token. This is used to capture error logs.
APP_ENV=<dev | prod>
PORT=<port number>
DATABASE_URL=<postgres database connection string>
AUTH_SECRET=<64-bit CSPRNG secret>
ROLLBAR_API_TOKEN=<Rollbar logging token> *Not required*
MAX_CONNECTION_POOL=<Max connections to pool for postgres database. Default is 20.> *Not required*
API_ROUTE_BASE=<API endpoint route base. Should not end with a forward slash (ex. baseterm/api). Default is an empty string.> *Not required*
Install the Docker Engine on the host machine. Docker Engine is currently available on a variety of Linux distros, macOS, and Windows 10 through Docker Desktop, and as a static binary installation.
Example
docker build --tag baseterm-api .
Example
docker run \
-d \
--expose 3000 \
-p 3000:3000 \
--env-file ".env" \
--name "baseterm-api" \
baseterm-api
Currently works on Linux, macOS, and Windows.
Install Python 3.9.x on the host machine. Please reference the Python documentation for setup.
npm ci
npm run build
pip3 install -r requirements.txt
npm run start
This launches a background process using pm2 and opens up the pm2 monitor. This monitor need not be kept open. Please reference the pm2 docs for interacting with the process.
{
Tbx = "tbx",
TbxHeader = "tbxHeader",
EncodingDesc = "encodingDesc",
P = "p",
RevisionDesc = "revisionDec",
Change = "change",
FileDesc = "fileDesc",
PublicationStmt = "publicationStmt",
SourceDesc = "sourceDesc",
TitleStmt = "titleStmt",
Title = "title",
Note = "note",
Text = "text",
Body = "body",
ConceptEntry = "conceptEntry",
LangSec = "langSec",
TermSec = "termSec",
Term = "term",
TermNoteGrp = "termNoteGrp",
TermNote = "termNote",
Back = "back",
RefObjectSec = "refObjectSec",
RefObject = "refObject",
ItemSet = "itemSet",
ItemGrp = "itemGrp",
Item = "item",
Admin = "admin",
AdminGrp = "adminGrp",
AdminNote = "adminNote",
Descrip = "descrip",
DescripGrp = "descripGrp",
DescripNote = "descripNote",
Date = "date",
Ref = "ref",
Transac = "transac",
TransacGrp = "transacGrp",
TransacNote = "transacNote",
Xref = "xref",
}
TbxElement.Admin |
TbxElement.AdminGrp |
TbxElement.Descrip |
TbxElement.DescripGrp |
TbxElement.Transac |
TbxElement.TransacGrp |
TbxElement.Note |
TbxElement.Ref |
TbxElement.Xref |
TbxElement.Date |
TbxElement.AdminNote |
TbxElement.DescripNote |
TbxElement.TransacNote
{
type: string;
style: string;
xmlns: string;
name: string;
termbaseUUID: UUID;
xmlLang: string;
enforceBasicDialect: boolean;
}
{
uuid: UUID;
termSecId: NullableString;
id: NullableString;
value: string;
language: string;
termbaseUUID: UUID;
order: number;
}
{
synonyms: TermPreview[];
translations: TermPreview[];
conceptId: string;
customers: string[];
partOfSpeech: string;
approvalStatus: string;
subjectField: string;
} & TermPreview
{
conceptEntry: ConceptEntryPreview;
languageSection: LanguageSectionPreview;
auxElements: AuxElement[];
termNotes: TermNote[];
}
{
uuid: UUID;
id: string;
termbaseUUID: string;
}
{
languageSections: LanguageSectionPreview[];
auxElements: AuxElement[];
} & ConceptEntryPreview
{
uuid: UUID;
termbaseUUID: string;
xmlLang: string;
order: number;
}
{
conceptEntry: ConceptEntryPreview;
auxElements: AuxElement[];
terms: TermPreview[];
} & LanguageSectionPreview
{
order: number;
id?: NullableString;
termbaseUUID?: UUID;
target?: NullableString;
xmlLang?: NullableString;
datatype?: NullableString;
type?: NullableString;
auxElements?: AuxElement[];
grpId?: NullableString;
uuid: UUID;
value: string;
elementType: TbxAuxElement,
}
{
uuid: UUID;
xmlLang: NullableString;
target: NullableString;
termbaseUUID: UUID;
type: string;
value: string;
order: number;
elementType: TbxElement.TermNote | TbxElement.TermNoteGrp
}
{
id: NullableString;
grpId: NullableString;
datatype: NullableString;
auxElements?: AuxElement[]
} & TermNotePreview
{
uuid: UUID,
id: string,
source: "BaseTerm" | "External"
}
Parameters are required unless otherwise specified.
Validate
/validate
POST
@tbxFile (FormData)
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 400 (Bad Request)
Body: {
error: "TBX File is invalid:
<error appended here>"
}
Status Code: 200 (Success)
Body: {
tbx: TbxObject
}
An example of a TbxObject can be found in the repository.
Import
/import
POST
Admin
Staff
@tbxFile (FormData)
@name
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 400 (Bad Request)
Body: {
error: "TBX File is invalid:
<error appended here>"
}
Status Code: 202 (Accepted)
Body: {
sessionId: UUID,
termbaseUUID: UUID,
}
The import endpoint launches a session. To subscribe to the session that is launched, the sessionId will need to be used with the session endpoint.
Export
/export/:termbaseUUID
GET
Admin
Staff
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 202 (Accepted)
Body: {
sessionId: UUID,
}
The export endpoint launches a session. To subscribe to the session that is launched, the sessionId will need to be used with the session endpoint via HTTP SSE.
Session
/session/:sessionId
GET
Admin
Staff
{
type?: "import" | "export",
status?: "in progress" | "completed",
conceptEntryNumber?: number;
conceptEntryCount?: number;
data?: string;
error?: string;
errorCode?: number;
}
The session endpoint utilizes Server-Side Events (SSE), so the client will have to subscribe to the endpoint using EventSource.
Get Termbase
/termbase/:termbaseUUID
GET
Admin
Staff
User
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 200 (Success)
Body: {
metadata: {
languages: string[],
partsOfSpeech: string[],
customers: string[],
conceptIds: string[],
approvalStatuses: string[],
subjectFields: string[],
personRefs: PersonRefObjectPreview[],
}
} & Termbase
Get All Termbases
/termbases?page=:paginationPage
GET
Admin
Staff
User
Status Code: 400 (Bad Request)
Body: {
error: "Invalid query params supplied."
}
Status Code: 200 (Success)
Body: {
termbases: Termbase[],
pagination: {
page: number;
pageCount: number;
perPage: number;
totalCount: number;
}
}
Create Termbase
/termbase
POST
Admin
Staff
@name
@lang
@description (optional)
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 409 (Conflict)
Body: {
error: "A base already exists with the same name."
}
Status Code: 200 (Success)
Body: {
uuid: UUID
}
Update Termbase
/termbase/:termbaseUUID
PATCH
Admin
Staff
@type (optional)
@name (optional)
@enforceBasicDialect (optional)
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 409 (Conflict)
Body: {
error: "A base already exists with the same name."
}
Status Code: 200 (Success)
Body: Termbase
enforceBasicDialect is initially true when a termbase is either uploaded or created. Once set to false, the parameter can not be changed.
type can only be updated once enforceBasicDialect is set to false.
Delete Termbase
/termbase/:termbaseUUID
DELETE
Admin
Status Code: 204 (Success with no content)
Body: {}
Get Term
/termbase/:termbaseUUID/term/:termUUID
GET
Admin
Staff
User
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 200 (Success)
Body: TermFullView
Get All Terms
/termbase/:termbaseUUID/terms?page=:paginationPage
GET
Admin
Staff
User
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 400 (Bad Request)
Body: {
error: "Invalid query params supplied."
}
Status Code: 200 (Success)
Body: {
terms: TermPartialView[],
pagination: {
page: number;
pageCount: number;
perPage: number;
totalCount: number;
}
}
Create Term
/termbase/:termbaseUUID/term
POST
@langSecUUID
@value
Admin
Staff
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 200 (Success)
Body: {
uuid: UUID
}
Update Term
/termbase/:termbaseUUID/term/:termUUID
PATCH
@id (optional)
@order (optional)
@value (optional)
@termSecId (optional)
Admin
Staff
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 200 (Success)
Body: TermPreview
Delete Term
/termbase/:termbaseUUID/term/:termUUID
DELETE
Admin
Staff
Status Code: 400 (Bad Request)
Body: {
error: "Language Sections must have at least one term."
}
Status Code: 204 (Success with no content)
Body: {}
Create Term Note
/termbase/:termbaseUUID/termNote
POST
@isGrp
@type
@value
@termUUID
Admin
Staff
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 200 (Success)
Body: {
uuid: UUID
}
Update Term Note
/termbase/:termbaseUUID/termNote/:termNoteUUID
PATCH
@id (optional)
@type (optional)
@value (optional)
@grpId (optional)
@target (optional)
@datatype (optional)
@langCode (optional)
@order (optional)
Admin
Staff
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 400 (Bad Request)
Body: {
error: "Target does not reference a known ID"
}
Status Code: 400 (Bad Request)
Body: {
error: "ID is invalid. ID must follow convention for XML."
}
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 409 (Conflict)
Body: {
error: "A TBX element already exists with the same ID."
}
Status Code: 200 (Success)
Body: TermNotePreview
Delete Term Note
/termbase/:termbaseUUID/termNote/:termNoteUUID
DELETE
Admin
Staff
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 204 (Success with no content)
Body: {}
Create Person Ref Object
/termbase/:termbaseUUID/personRefObject
POST
Admin
Staff
User
@name
@email
@role
@id
The resource will only be created if the requester's user id is the same as the request's id.
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 400 (Bad Request)
Body: {
error: "The supplied user id does not match the requester's user id."
}
Status Code: 400 (Bad Request)
Body: {
error: "Person ID must be a UUID."
}
Status Code: 409 (Conflict)
Body: {
error: "A TBX element already exists with the same ID."
}
Status Code: 200 (Success)
Body: {
uuid: UUID
}
Get Language Section
/termbase/:termbaseUUID/langSec/:langSecUUID
GET
Admin
Staff
User
Status Code: 404 (Not Found)
Body: {
error: "Resource not found."
}
Status Code: 200 (Success)
Body: LanguageSection
Create Language Section
/termbase/:termbaseUUID/langSec
POST
Admin
Staff
@entryUUID
@langCode
@initialTerm
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 200 (Success)
Body: {
uuid: UUID
}
Update Language Section
/termbase/:termbaseUUID/langSec/:langSecUUID
PATCH
Admin
Staff
@langCode (optional)
@order (optional)
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 200 (Success)
Body: LanguageSectionPreview
Delete Language Section
/termbase/:termbaseUUID/langSec/:langSecUUID
DELETE
Admin
Staff
Status Code: 400 (Bad Request)
Body: {
error: "Concept entries must have at least one language section."
}
Status Code: 204 (Success with no content)
Body: {}
Get Concept Entry
/termbase/:termbaseUUID/entry/:entryUUID
GET
Admin
Staff
User
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 200 (Success)
Body: ConceptEntry
Create Concept Entry
/termbase/:termbaseUUID/entry
POST
Admin
Staff
@entryId
@initialLanguageSection
@initialTerm
Status Code: 409 (Conflict)
Body: {
error: "A TBX element already exists with the same ID."
}
Status Code: 400 (Bad Request)
Body: {
error: "ID is invalid. ID must follow convention for XML."
}
Status Code: 200 (Success)
Body: {
uuid: UUID
}
Update Concept Entry
/termbase/:termbaseUUID/entry/:entryUUID
PATCH
Admin
Staff
@id (optional)
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 409 (Conflict)
Body: {
error: "A TBX element already exists with the same ID."
}
Status Code: 400 (Bad Request)
Body: {
error: "ID is invalid. ID must follow convention for XML."
}
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 200 (Success)
Body: ConceptEntryPreview
Delete Concept Entry
/termbase/:termbaseUUID/entry/:entryUUID
DELETE
Admin
Staff
Status Code: 204 (Success with no content)
Body: {}
Create Aux Element
/termbase/:termbaseUUID/auxElement
POST
Admin
Staff
@parentElementType (TbxElement)
@parentUUID
@value
@elementType
@type (optional)
@target (optional)
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 200 (Success)
Body: {
uuid: UUID
}
Although type is listed as an optional request parameter, the inclusion of this parameter depends on whether or not the auxiliary element being created requires a type attribute.
Update Aux Element
/termbase/:termbaseUUID/auxElement/:auxElementUUID
PATCH
Admin
Staff
@elementType (TbxElement)
@id (optional)
@grpId (optional)
@order (optional)
@target (optional)
@langCode (optional)
@datatype (optional)
@type (optional)
@value (optional)
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 400 (Bad Request)
Body: {
error: "Target does not reference a known ID"
}
Status Code: 400 (Bad Request)
Body: {
error: "ID is invalid. ID must follow convention for XML."
}
Status Code: 404 (Not Found)
Body: {
error: "Resource not found"
}
Status Code: 409 (Conflict)
Body: {
error: "A TBX element already exists with the same ID."
}
Status Code: 200 (Success)
Body: AuxElement
Delete Aux Element
/termbase/:termbaseUUID/auxElement/:auxElementUUID
DELETE
Admin
Staff
@elementType (TbxElement)
Status Code: 400 (Bad Request)
Body: {
error: "Body Invalid"
}
Status Code: 204 (Success with no content)
Body: {}