Version: ClientApi v1.2.1 https://api.sltt-bible.net
Introduction
Welcome to the SLTT Client API!
This API documentation page was created with Slate.
Your org is your partner
In the SLTT Client API, your organization is referred to as your partner. So, when you see partnerId in the documentation, it refers to your organization's id in SLTT. Usually this is the primary email domain name for your organization. Most endpoints will be based on /partner or /batch/partner endpoints, indicating that the data is filtered by your partner's projects and roles.
Authentication (Basic Auth)
SLTT Client API authentication is basic authentiaton based on a public/secret token pair associated with your client and your organization (remember, in this api your organization referred to as your partner).
curl --request GET \
--url "api_endpoint_here" \
-u {client_id}:{token}
If you haven't already received a clientId and token pair, please see Appendix 2: Apply for an api token.
All requests to the SLTT Client API require basic authentication using your clientId and token pair.
The clientId should be the basic auth user and the token will be the basic auth password.
For example, if you have a
clientId
client--createdAt--1696539988381--partnerId--example.com
and a
token
aeb433366bce021414c288bb9e5ff992
for curl you would join them with a colon (:) to form the basic auth -u
user:passwordcredentials:
-u client--createdAt--1696539988381--partnerId--example.com:aeb433366bce021414c288bb9e5ff992
for other REST clients, you may need to base 64 encode the
user:passwordjoined string for theAuthorizationheader:
{ "Authorization": "Basic Y2xpZW50LS1jcmVhdGVkQXQtLTE2OTY1Mzk5ODgzODEtLXBhcnRuZXJJZC0tZXhhbXBsZS5jb206YWViNDMzMzY2YmNlMDIxNDE0YzI4OGJiOWU1ZmY5OTI=" }
Get api docs (no auth)
This provides this client api documentation
HTTP Request
curl --request GET \
--url https://api.sltt-bible.net
GET https://https://api.sltt-bible.net
Response Example
(These api docs)
Get projects and partner roles
This provides a simple listing of project ids and the roles that your partnerId plays in those projects
HTTP Request
curl --request GET \
--url https://api.sltt-bible.net/partner/projects \
-u client--createdAt--1696539988381--partnerId--example.com:aeb433366bce021414c288bb9e5ff992
GET https://https://api.sltt-bible.net/partner/projects -u {clientId}:{token}
Response Example
[
{
"partnerId": "your.example.partner-id",
"projectId": "YourExampleProject",
"roles": [
"consultant"
],
"source": "system"
}
]
Response Schema
type GetPartnerProjectsResponse = {
projectId: string
partnerId: string
roles: PartnerRole[]
source: PartnerSource
}[]
enum PartnerRole {
admin = ProjectMemberRole.admin,
translator = ProjectMemberRole.translator,
consultant = ProjectMemberRole.consultant,
interpreter = ProjectMemberRole.interpreter,
observer = ProjectMemberRole.observer,
sysops = 'sysops', // SLTT system/sysops for (root admins)
}
// system or a domain export that provided the role data
enum PartnerSource {
system = 'system',
stuartt = 'stuartt@doorinternational.org',
esampson = 'esampson@biblesocieties.org'
}
enum ProjectMemberRole {
admin = 'admin',
translator = 'translator',
consultant = 'consultant',
interpreter = 'interpreter',
observer = 'observer',
}
Batch get project metadata
This provides basic project metadata for all the projects that your partnerId is associated with
HTTP Request
curl --request GET \
--url https://api.sltt-bible.net/batch/partner/projects/metadata \
-u client--createdAt--1696539988381--partnerId--example.com:aeb433366bce021414c288bb9e5ff992
GET https://https://api.sltt-bible.net/batch/partner/projects -u {clientId}:{token}
NOTE: /batch/ endpoints may require pagination of projectIds if there are results from more than 100 projects.
See Appendix 1: Request Pagination section below for details.
Response Example
{
"batchSummary": {
"partnerId": "your.example.partner-id",
"unprocessed": {
"count": 0,
"queryParams": {
"batchGetKeyLimit": 100,
"unprocessedKeys": "",
}
},
"processed": {
"count": 1,
"projectIds": "YourExampleProject1,YourExampleProject2"
}
},
"batchResponse": [
{
"name": "YourExampleProject1",
"displayName": "Your Example Project",
"description": "",
"region": "africa",
"projectType": "translation",
"language": "",
"lastUpdated": "2023/02/09 12:17:01.975Z",
"plannedCompletionDate": "",
"progress": 0,
"lastVideoAt": "2023-12-13T08:38:16.351Z",
"lastNoteAt": "2024-01-12T09:22:28.318Z",
"totalVideos": 5,
"totalNotes": 48,
"activityStatus": "trained",
"teamId": "Egypt-1"
},
//...
]
}
Response Schema
type GetBatchPartnerProjectsMetadataResponse = {
batchSummary: {
partnerId: string,
unprocessed: {
count: number,
queryParams: {
batchGetKeyLimit: number /* default is 100 */,
unprocessedKeys: CommaSeparatedListString /* query parameter and value for pagination */,
}
},
processed: {
count: number,
projectIds: CommaSeparatedListString,
},
},
batchResponse: ProjectMetadataBasic[]
}
type ProjectMetadataBasic = {
name: string
displayName: string
description: string
language: string // (currently unused)
progress: number // % total project complete, e.g. '33.1'
plannedCompletionDate: string // yyyy-mm-dd (currently unused)
lastUpdated: string // yyyy-mm-dd
lastVideoAt?: string // ISO Date/Time
lastNoteAt?: string // ISO Date/Time
activityStatus: ProjectStatus
totalVideos: number
totalNotes: number
projectType: ProjectType
region: Region
teamId: string // can be used to group projects
}
enum ProjectStatus {
inactive = 'inactive' /* never trained and no recent note or video activity */,
trained = 'trained' /* more than 20 notes or videos posted */,
training = 'training' /* has recent note or video activity */,
active = 'active' /* is trained and has recent note or video activity */,
}
type ProjectType = 'translation' | 'additional' | 'test_training' | 'resource' | 'other' | ''
type Region = 'africa' | 'americas' | 'asia' | 'europe' | 'oceania' | ''
type CommaSeparatedListString = string /* comma separated list in string "a,b,c" */
Batch get partners
This provides a list of all the partners (and their project roles) that your (partner's) projects have
HTTP Request
curl --request GET \
--url https://api.sltt-bible.net/batch/partner/partners \
-u client--createdAt--1696539988381--partnerId--example.com:aeb433366bce021414c288bb9e5ff992
GET https://https://api.sltt-bible.net/batch/partner/partners -u {clientId}:{token}
Response Example
{
"batchSummary": {
"partnerId": "system",
"unprocessed": {
"count": 0,
"queryParams": {
"batchGetKeyLimit": 200,
"unprocessedKeys": "",
}
},
"processed": {
"count": 2,
"roles": "admin,consultant,interpreter,observer,sysops,translator",
"partnerIds": "wycliffebenin.org,partner.2",
"projectIds": "YourExampleProject,YourExampleProject2",
"bytes": 46507,
"timeTaken": 501
}
},
"batchResponse": [
{
"projectId": "YourExampleProject",
"partnerId": "system",
"roles": [
"sysops"
]
},
{
"projectId": "YourExampleProject",
"partnerId": "your.example.partner-id",
"roles": [
"consultant"
]
},
//...
],
}
Response Schema
export type GetBatchPartnerProjectsPartnersResponse = {
batchSummary: {
partnerId: string,
unprocessed: {
count: number,
projectIds: CommaSeparatedListString,
queryParams: {
batchGetKeyLimit: number,
unprocessedKeys: CommaSeparatedListString,
}
},
processed: {
count: number,
roles: CommaSeparatedListString,
partnerIds: CommaSeparatedListString,
projectIds: CommaSeparatedListString,
bytes: number,
},
},
batchResponse: GetProjectPartnersResponse[]
}
type ProjectPartnersItem = {
partnerId: string,
projectId: string,
roles: PartnerRole[],
source: PartnerSource,
}
export type GetProjectPartnersResponse = ProjectPartnersItem[]
enum PartnerRole {
admin = ProjectMemberRole.admin,
translator = ProjectMemberRole.translator,
consultant = ProjectMemberRole.consultant,
interpreter = ProjectMemberRole.interpreter,
observer = ProjectMemberRole.observer,
sysops = 'sysops', // SLTT system/sysops for (root admins)
}
enum ProjectMemberRole {
admin = 'admin',
translator = 'translator',
consultant = 'consultant',
interpreter = 'interpreter',
observer = 'observer',
}
type CommaSeparatedListString = string /* comma separated list in string "a,b,c" */
Batch get passages
This provides a list of all the passages (and their tasks) that your (partner's) projects have
HTTP Request
curl --request GET \
--url https://api.sltt-bible.net/batch/partner/passages \
-u client--createdAt--1696539988381--partnerId--example.com:aeb433366bce021414c288bb9e5ff992
GET https://https://api.sltt-bible.net/batch/partner/passages -u {clientId}:{token}
NOTE: The cursor query parameter should be used with the GET /partner/projects/{projectsId}/passages
endpoint to paginate through a project's passages if GET /batch/partner/passages
returns its projectId in batchSummary.unprocessed.projectIdsWithCursors and its cursor is present
in its batchResponse[].summary.unprocessed.queryParams.cursor
ALSO IMPORTANT: The client will be responsible for merging the paginated passages data from the different requests. Also, the summary shows the passages/portions for the paginated data, not all the passages/portions for the project.
Response Example
{
"batchSummary": {
"partnerId": "system",
"unprocessed": {
"count": 1,
"projectIdsWithCursors": [],
"queryParams": {
"batchGetKeyLimit": 2,
"unprocessedKeys": "YourExampleProject3"
}
},
"processed": {
"count": 2,
"projectIds": "YourExampleProject1,YourExampleProject2",
"bytes": 90615,
"timeTaken": 504
}
},
"batchResponse": [
{
"summary": {
"partnerId": "system",
"projectId": "YourExampleProject1",
"unprocessed": {
"queryParams": {
"cursor": null
}
},
"processed": {
"stagesCount": 4,
"tasksCount": 8,
"taskDifficulties": [
" 0,1,1,1,1,1,1,0"
],
"passageCounts": [
"64,0,0,0,0,0,0,0"
],
"passageCountsByPortion": [
" 4,0,0,0,0,0,0,0 - KGH 05",
" 4,0,0,0,0,0,0,0 - KGH 06",
" 4,0,0,0,0,0,0,0 - KGH 07",
" 4,0,0,0,0,0,0,0 - KGH 08",
" 4,0,0,0,0,0,0,0 - KGH 09",
" 4,0,0,0,0,0,0,0 - KGH 10",
" 4,0,0,0,0,0,0,0 - KGH 11",
" 4,0,0,0,0,0,0,0 - KGH 12",
" 4,0,0,0,0,0,0,0 - KGH 13",
" 4,0,0,0,0,0,0,0 - KGH 16",
" 4,0,0,0,0,0,0,0 - KGH 17",
" 4,0,0,0,0,0,0,0 - KGH 18",
" 4,0,0,0,0,0,0,0 - KGH 19",
" 4,0,0,0,0,0,0,0 - KGH 20",
" 4,0,0,0,0,0,0,0 - KGH 22",
" 4,0,0,0,0,0,0,0 - KGH 31 B"
],
"portionsCount": 16,
"passagesCount": 64,
"passagesInProgressCount": 0,
"bytes": 11998
}
},
"response": {
"project": {
"name": "YourExampleProject1",
"displayName": "Your Example Project 1",
"description": "",
"language": "",
"progress": 0,
"plannedCompletionDate": "",
"lastUpdated": "2023/02/09 12:17:01.975Z",
"lastVideoAt": "2023-12-13T08:38:16.351Z",
"lastNoteAt": "2024-01-12T09:22:28.318Z",
"activityStatus": "trained",
"totalVideos": 5,
"totalNotes": 48,
"projectType": "translation",
"region": "africa",
"teamId": "YourTeamId"
},
"tasks": [
{
"taskId": "Not started",
"taskName": "Not started",
"bars": "|◇ ◻ ◻ ◻ ◻ ◻ ◻ ◇ 0%",
"difficulty": 0,
"difficultyPercent": 0,
"stageId": "Not started"
},
{
"taskId": "1.1",
"taskName": "First Draft",
"bars": " ◇|◻ ◻ ◻ ◻ ◻ ◻ ◇ 0%",
"difficulty": 1,
"difficultyPercent": 16.67,
"stageId": "1"
},
{
"taskId": "1.2",
"taskName": "Review First Draft",
"bars": " ◇ ◼|◻ ◻ ◻ ◻ ◻ ◇ 16.67%",
"difficulty": 1,
"difficultyPercent": 16.67,
"stageId": "1"
},
//...
{
"taskId": "2.2",
"taskName": "Third Draft",
"bars": " ◇ ◼ ◼ ◼ ◼ ◼|◻ ◇ 83.33%",
"difficulty": 1,
"difficultyPercent": 16.67,
"stageId": "2"
},
{
"taskId": "Finished",
"taskName": "Finished",
"bars": " ◇ ◼ ◼ ◼ ◼ ◼ ◼|✓ 100%",
"difficulty": 0,
"difficultyPercent": 0,
"stageId": "Finished"
}
],
"passages": [
{
"entityId": "230209_114806/230209_120913",
"passageName": "01.Topic",
"taskId": "Not started",
"bars": "|◇ ◻ ◻ ◻ ◻ ◻ ◻ ◇ 0%",
"difficulty": 1,
"portionName": "KGH 05",
"scripture": "GEN 7:1-24"
},
//...
],
},
},
]
}
Response Schema
export type GetBatchPartnerPassagesResponse = {
batchSummary: {
partnerId: string,
unprocessed: {
count: number,
projectIdsWithCursors: string[],
queryParams: {
eachGetItemsLimit: number,
batchGetKeyLimit: number,
unprocessedKeys: CommaSeparatedListString,
}
},
processed: {
count: number,
projectIds: CommaSeparatedListString,
bytes: number,
timeTaken: number /* in milliseconds */,
}
},
batchResponse: GetPartnerProjectPassagesResponse[]
}
export type GetPartnerProjectPassagesResponse = {
summary: {
partnerId: string,
projectId: string,
unprocessed: {
queryParams: {
getItemsLimit: number,
cursor: string,
}
},
processed: {
stagesCount: number,
tasksCount: number,
taskDifficulties: string[],
passageCounts: string[],
passageCountsByPortion: string[],
portionsCount: number,
passagesCount: number,
passagesInProgressCount: number,
bytes: number,
},
},
response: PartnerProjectPassagesResponse
}
type PartnerProjectPassagesResponse = {
project: ProjectMetadataBasic,
tasks: ProjectTaskForApi[],
passages: ProjectPassageForApi[],
}
export type ProjectTaskForApi = {
taskId: string
taskName: string
bars: string // " ◇ ◼ ◼ ◼ ◼ ◼|◻ ◇ 83.33%"
difficulty: number
stageId: string
}
export type ProjectPassageForApi = {
entityId: string
difficulty: number // e.g. 2.0 for a passage twice as hard as average passage
passageName: string // e.g. 'Second Passage'
taskId: string // e.g. '1.1'` (status of this passage)
bars: string // " ◇ ◼ ◼ ◼ ◼ ◼|◻ ◇ 83.33%"
portionName: string // e.g. 'First Portion'
scripture?: string, // "GEN 9:18-28, 10:1, 11:1 - 11:9; JHN 20:1-18"
scriptureErrors?: RefRangeString, // e.g. space-separated list of invalid references or ranges '001100-001001100 002999' (Genesis 100 - 1:100; Exodus 999)
}
type CommaSeparatedListString = string /* comma separated list in string "a,b,c" */
Get project passages
This provides a list of a single project's passages (and their tasks)
HTTP Request
curl --request GET \
--url https://api.sltt-bible.net/partner/projects/YourExampleProject1/passages \
-u client--createdAt--1696539988381--partnerId--example.com:aeb433366bce021414c288bb9e5ff992
GET https://https://api.sltt-bible.net/partner/projects/{projectId}/passages -u {clientId}:{token}
NOTE: The cursor query parameter should be used with the GET /partner/projects/{projectsId}/passages endpoint
to paginate through a project's passages if its response.summary.unprocessed.queryParams.cursor is present.
(Likewise, if GET /batch/partner/passages returns its projectId in batchSummary.unprocessed.projectIdsWithCursors
and its cursor is present in its batchResponse[].summary.unprocessed.queryParams.cursor)
ALSO IMPORTANT: The client will be responsible for merging the paginated passages data from the different requests. Also, the summary shows the passages/portions for the paginated data, not all the passages/portions for the project.
Response Example
{
"summary": {
"partnerId": "system",
"projectId": "YourExampleProject1",
"unprocessed": {
"queryParams": {
"cursor": null
}
},
"processed": {
"stagesCount": 4,
"tasksCount": 8,
"taskDifficulties": [
" 0,1,1,1,1,1,1,0"
],
"passageCounts": [
"64,0,0,0,0,0,0,0"
],
"passageCountsByPortion": [
" 4,0,0,0,0,0,0,0 - KGH 05",
" 4,0,0,0,0,0,0,0 - KGH 06",
" 4,0,0,0,0,0,0,0 - KGH 07",
" 4,0,0,0,0,0,0,0 - KGH 08",
" 4,0,0,0,0,0,0,0 - KGH 09",
" 4,0,0,0,0,0,0,0 - KGH 10",
" 4,0,0,0,0,0,0,0 - KGH 11",
" 4,0,0,0,0,0,0,0 - KGH 12",
" 4,0,0,0,0,0,0,0 - KGH 13",
" 4,0,0,0,0,0,0,0 - KGH 16",
" 4,0,0,0,0,0,0,0 - KGH 17",
" 4,0,0,0,0,0,0,0 - KGH 18",
" 4,0,0,0,0,0,0,0 - KGH 19",
" 4,0,0,0,0,0,0,0 - KGH 20",
" 4,0,0,0,0,0,0,0 - KGH 22",
" 4,0,0,0,0,0,0,0 - KGH 31 B"
],
"portionsCount": 16,
"passagesCount": 64,
"passagesInProgressCount": 0,
"bytes": 11998
}
},
"response": {
"project": {
"name": "YourExampleProject1",
"displayName": "Your Example Project 1",
"description": "",
"language": "",
"progress": 0,
"plannedCompletionDate": "",
"lastUpdated": "2023/02/09 12:17:01.975Z",
"lastVideoAt": "2023-12-13T08:38:16.351Z",
"lastNoteAt": "2024-01-12T09:22:28.318Z",
"activityStatus": "trained",
"totalVideos": 5,
"totalNotes": 48,
"projectType": "translation",
"region": "africa",
"teamId": "YourTeamId"
},
"tasks": [
{
"taskId": "Not started",
"taskName": "Not started",
"bars": "|◇ ◻ ◻ ◻ ◻ ◻ ◻ ◇ 0%",
"difficulty": 0,
"difficultyPercent": 0,
"stageId": "Not started"
},
// ...
],
"passages": [
{
"entityId": "230209_114806/230209_120913",
"passageName": "01.Topic",
"taskId": "Not started",
"bars": "|◇ ◻ ◻ ◻ ◻ ◻ ◻ ◇ 0%",
"difficulty": 1,
"portionName": "KGH 05",
"scripture": "GEN 7:1-24"
},
//...
],
},
}
Response Schema
export type GetPartnerProjectPassagesResponse = {
summary: {
partnerId: string,
projectId: string,
unprocessed: {
queryParams: {
getItemsLimit: number,
cursor: string,
}
},
processed: {
stagesCount: number,
tasksCount: number,
taskDifficulties: string[],
passageCounts: string[],
passageCountsByPortion: string[],
portionsCount: number,
passagesCount: number,
passagesInProgressCount: number,
bytes: number,
},
},
response: PartnerProjectPassagesResponse
}
type PartnerProjectPassagesResponse = {
project: ProjectMetadataBasic,
tasks: ProjectTaskForApi[],
passages: ProjectPassageForApi[],
}
export type ProjectTaskForApi = {
taskId: string
taskName: string
bars: string // " ◇ ◼ ◼ ◼ ◼ ◼|◻ ◇ 83.33%"
difficulty: number
stageId: string
}
export type ProjectPassageForApi = {
entityId: string
difficulty: number // e.g. 2.0 for a passage twice as hard as average passage
passageName: string // e.g. 'Second Passage'
taskId: string // e.g. '1.1'` (status of this passage)
bars: string // " ◇ ◼ ◼ ◼ ◼ ◼|◻ ◇ 83.33%"
portionName: string // e.g. 'First Portion'
scripture?: string, // "GEN 9:18-28, 10:1, 11:1 - 11:9; JHN 20:1-18"
scriptureErrors?: RefRangeString, // e.g. space-separated list of invalid references or ranges '001100-001001100 002999' (Genesis 100 - 1:100; Exodus 999)
}
type CommaSeparatedListString = string /* comma separated list in string "a,b,c" */
Get project events
This provides a list of a single project's (passage and video) events
HTTP Request
curl --request GET \
--url https://api.sltt-bible.net/partner/projects/YourExampleProject1/events \
-u client--createdAt--1696539988381--partnerId--example.com:aeb433366bce021414c288bb9e5ff992
GET https://https://api.sltt-bible.net/partner/projects/{projectId}/events -u {clientId}:{token}
NOTE: The cursor query parameter should be used with the GET /partner/projects/{projectsId}/events endpoint
to paginate through a project's events if its response.summary.unprocessed.queryParams.cursor is present.
For more information see the Appendix 1: Request Pagination section below.
NOTE: date may not be in sequential (eseq) order, due to the nature of events being made locally first (sometimes offline) and then later synced to the server.
NOTE: For older updated/removed/resolved/unresolved events (before Aug 2024), eventType will show creator along with the creator's emailHash, userRole and info. This is not necessarily the same user who actually performed the update. Newer updated events should instead show modifier and the correct emailHash, userRole, and info for who actually performed the update. (The dashboard detailed events export has the same issue.)
Response Example
{
"summary": {
"partnerId": "system",
"projectId": "YourExampleProject1",
"unprocessed": {
"queryParams": {
"cursor": "eyJwayI6IiRzbHR0LWFwaSNwcm9qZWN0aWRfc3N0cnMiLCJzayI6IiRldmVudHNfMSNlc2VxXzAwMDAwMDMyNTUifQ"
}
},
"processed": {
"eventsCount": 3255,
"bytes": 1347702
}
},
"response": {
"events": [
{
"eseq": 1,
"date": "2020/05/11 09:35",
"oseq": 10,
"event": "passage_created",
"entity": "passage",
"eventType": "created",
"removed": false,
"entityId": "200511_003121/200511_003536",
"portionId": "200511_003121",
"passageId": "200511_003536",
"portionName": "FGH#56",
"passageName": "Story#56",
"difficulty": 1,
"taskId": "Not started",
"emailHash": "19088a8b1e69cb8f",
"eventRole": "creator",
"info": "creator: translator 19088a8b1e69cb8f",
"userRole": "translator",
"projectId": "YourExampleProject1"
},
{
"eseq": 2,
"date": "2020/05/11 09:36",
"oseq": 11,
"event": "video_post",
"entity": "video",
"eventType": "post",
"removed": false,
"entityId": "200511_003121/200511_003536/200511_003537",
"portionId": "200511_003121",
"passageId": "200511_003536",
"portionName": "FGH#56",
"passageName": "Story#56",
"emailHash": "19088a8b1e69cb8f",
"eventRole": "creator",
"info": "creator: translator 19088a8b1e69cb8f",
"userRole": "translator",
"projectId": "YourExampleProject1"
},
{
"eseq": 3,
"date": "2020/05/11 09:37",
"oseq": 12,
"event": "passage_removed",
"entity": "passage",
"eventType": "removed",
"removed": true,
"entityId": "200511_003121/200511_003536",
"portionId": "200511_003121",
"passageId": "200511_003536",
"portionName": "FGH#56",
"passageName": "Story#56",
"difficulty": 1,
"taskId": "Not started",
"emailHash": "70ddfbb6b68ae7ad",
"eventRole": "modifier", // older events (before Aug 2024) show "creator" user instead of "modifier" user
"info": "modifier: admin 70ddfbb6b68ae7ad",
"userRole": "admin",
"projectId": "YourExampleProject1"
},
// ...
]
}
}
Response Schema
export type GetPartnerEventsResponse = {
summary: {
partnerId: string,
projectId: string,
unprocessed: {
queryParams: {
getItemsLimit: number,
cursor: string,
}
},
processed: {
eventsCount: number,
cursor: string,
bytes: number,
},
},
response: PartnerProjectEventResponse
}
type PartnerProjectEventResponse = {
events: ProjectEventForApi[]
}
export type ProjectEventForApi = (PassageEventTypeForApi | VideoEventTypeForApi | NotYetSupportedDetailedEventForApi)
type PassageEventTypeForApi = {
eseq: number
date: string
oseq: number,
event: ProjectEventType
entity: EventEntity.Passage
eventType: BasicEventType
removed: boolean
entityId: string
portionId: string
passageId: string
portionName: string
passageName: string
difficulty: number
taskId: string
taskName: string
emailHash: string // 16 digit hash of user email
eventRole: EventRole
info: string
userRole: ProjectMemberRole
projectId: string
}
type VideoEventTypeForApi = {
eseq: number
date: string
event: ProjectEventType
entity: EventEntity.Video
eventType: PostableEventType.Post
removed: boolean
entityId: string
portionId: string
passageId: string
portionName: string
passageName: string
emailHash: string // 16 digit hash of user email
eventRole: EventRole
info: string
userRole: ProjectMemberRole
projectId: string
}
export enum EventEntity {
Passage = 'passage',
Video = 'video',
// NOTE: the following "detailed events" are available via dashboard.sltt-bible.net Passage Status > Download details as TSV
Task = 'task',
Portion = 'portion',
Note = 'note',
}
export enum ProjectEventType {
passage_created = 'passage_created',
passage_updated = 'passage_updated',
passage_removed = 'passage_removed',
video_post = 'video_post',
// NOTE: the following "detailed events" are currently only available via dashboard.sltt-bible.net Passage Status > Download details as TSV)
video_view = 'video_view', // detailed (via dashboard Passage Status > Download details as TSV)
note_post = 'note_post', // detailed (via dashboard Passage Status > Download details as TSV)
note_view = 'note_view', // detailed (via dashboard Passage Status > Download details as TSV)
note_resolved = 'note_resolved', // detailed (via dashboard Passage Status > Download details as TSV)
note_unresolved = 'note_unresolved', // detailed (via dashboard Passage Status > Download details as TSV)
portion_created = 'portion_created', // detailed (via dashboard Passage Status > Download details as TSV)
portion_removed = 'portion_removed', // detailed (via dashboard Passage Status > Download details as TSV)
}
export enum EventEntity {
Passage = 'passage',
Video = 'video',
// NOTE: the following "detailed events" are available via dashboard.sltt-bible.net Passage Status > Download details as TSV
Task = 'task',
Portion = 'portion',
Note = 'note',
}
export enum BasicEventType {
Created = 'created',
Updated = 'updated',
Removed = 'removed'
}
export enum PostableEventType {
Post = 'post',
// NOTE: the following "detailed events" are available via dashboard.sltt-bible.net Passage Status > Download details as TSV
View = 'view'
}
export enum NoteEventType {
// NOTE: the following "detailed events" are available via dashboard.sltt-bible.net Passage Status > Download details as TSV
Resolved = 'resolved',
Unresolved = 'unresolved'
}
enum EventRole {
Creator = 'creator',
Modifier = 'modifier',
// NOTE: the following "detailed events" are available via dashboard.sltt-bible.net Passage Status > Download details as TSV
Viewer = 'viewer'
}
enum ProjectMemberRole {
admin = 'admin',
translator = 'translator',
consultant = 'consultant',
interpreter = 'interpreter',
observer = 'observer',
}
Appendix 1. Request Pagination
A 1.1 /partner endpoints
/partner/ endpoints that provide a summary object if there is a cursor query parameter in
the summary.unprocessed.queryParams.cursor field. If so, then the client should pass the cursor
as a query parameter for the next request.
For example,
{
"summary": {
"projectId": "Your-Example-Project",
"partnerId": "your.example.partner-id",
"unprocessed": {
"count": 0,
"queryParams": {
"cursor": "eyJwayI6IiRzbHR0LWFwaSNwcm9qZWN0aWRfeW91ci1leGFtcGxlLXByb2plY3QiLCJzayI6IiRldmVudHNfMSNlc2VxXzAwMDAwMDMyNTUifQ=="
//...
}
},
//...
}
}
To get the next page of results, pass the cursor as a query parameter for the next request:
curl --request GET \
--url https://api.sltt-bible.net/partner/projects?cursor=eyJwayI6IiRzbHR0LWFwaSNwcm9qZWN0aWRfeW91ci1leGFtcGxlLXByb2plY3QiLCJzayI6IiRldmVudHNfMSNlc2VxXzAwMDAwMDMyNTUifQ== \
-u client--createdAt--1696539988381--partnerId--example.com:aeb433366bce021414c288bb9e5ff992
A 1.2 /batch/ endpoints
/batch/ endpoints may require pagination of projectIds if results come from more projects than
the batchGetKeyLimit specified (default is 100 projects).
For as long as batchSummary.unprocessed.queryParams.unprocessedKeys is not empty in your last response,
pass its value (a comma-delimited list of projectIds) as a query parameter for the next request.
For example, in the Response example below, batchSummary.unprocessed.queryParams.unprocessedKeys
has __TESTnmX1__,__TESTnmX2__ for the request GET /batch/partner/projects?batchGetKeyLimit=1:
{
"batchSummary": {
"partnerId": "your.example.partner-id",
"unprocessed": {
"count": 2,
"projectIds": ["__TESTnmX1__", "__TESTnmX2__"],
"queryParams": {
"batchGetKeyLimit": 100,
"unprocessedKeys": "__TESTnmX1__,__TESTnmX2__",
}
},
"processed": {
"count": 1,
"projectIds": [
"YourExampleProject"
]
},
},
//...
}
So the follow up request should look like
curl --request GET \
--url https://api.sltt-bible.net/batch/partner/projects?unprocessedKeys=__TESTnmX1__,__TESTnmX2__ \
-u client--createdAt--1696539988381--partnerId--example.com:aeb433366bce021414c288bb9e5ff992
Alternatively, if you think the request can complete within the timeout period (default is 10 seconds),
you can pass a new batchGetKeyLimit that contains more than the projects you expect to get back (?batchGetKeyLimit=1000)
curl --request GET \
--url https://api.sltt-bible.net/batch/partner/projects?batchGetKeyLimit=1000 \
-u client--createdAt--1696539988381--partnerId--example.com:aeb433366bce021414c288bb9e5ff992
Appendix 2. Apply for an api token
A 2.1 Send an email
Example email:
To: epyle+sltt-client-api@biblesocieties.org
From: "Jon Doh"<jon.doh@example.com>
Subject: SLTT Client API Token Request
Hi, I'm Jon Doh from example.com. We would like to request a token for the SLTT Client API.
Here is the client information you requested:
Organization domain name: example.com
Contact name: Jon Doh
Contact email: jon.doh@example.com
Client description: example.com DOMO monthly SLTT usage report
Thank you so much for your help!
Jon
To apply for an api token, please contact the SLTT tech lead at epyle+sltt-client-api@biblesocieties.org.
You will need to email the following information for your client:
- Organization domain name: The primary domain name for your organization
- Contact name: The primary person responsible for handling your client's technical support issues
- Contact email: The email address for the technical contact person
- Client description: A brief description of the client's intended usage of the SLTT system API
A 2.2 Receive clientId email
Within the next day or so, you should receive two separate emails. One with your clientId and another with your token to use for basic authentication.
Example reply:
------- reply --------
To: "Jon Doh"<jon.doh@example.com>
From: epyle+sltt-client-api@biblesocieties.org
Subject: Your SLTT Client API Token Request
Hi, Your SLTT Client api token application was granted. Here is your client profile including your
clientId. Your token will be sent in a separate email.
{
"partnerId": "example.com",
"contactName": "Jon Doh",
"contactEmail": "jon.doh@example.com",
"clientDescription": "example.com DOMO monthly SLTT usage report",
"clientId": "client--createdAt--1696539988381--partnerId--example.com",
}
Let me know if you need any further help!
Eric
A 2.3 Receive token email
Example reply:
------- reply --------
To: "Jon Doh"<jon.doh@example.com>
From: epyle+sltt-client-api@biblesocieties.org
Subject: follow-up email
Hi, Jon,
Here's the other information you will need:
{
"token": "aeb433366bce021414c288bb9e5ff992",
}
Again, let me know if you need any further help!
Eric