Loopwise Admin API Queries
Available query operations, pagination, and filtering for the Loopwise Admin API
Note: The Loopwise Admin API is currently under development and not yet available for public use. This documentation is provided for preview purposes only.
Overview
The Loopwise Admin API provides a variety of query operations to retrieve data from your school. This section documents all available queries, along with concepts like pagination and filtering that apply across multiple query types.
Available Resources
The API provides queries for the following resources:
- Courses: Access course information
- Students: Retrieve student data
- Assignments: Get assignment details
- Events: Access school calendar events
- Coupons: Retrieve discount coupon information
- Membership Plans: Access subscription plan details
- Payments: Query payment transactions and refunds
- Subscriptions: Retrieve user subscription information
- Users: Retrieve user information
Common Parameters
All queries accept the following common parameters:
| Parameter | Type | Description |
|---|---|---|
first | Int | Number of items to return (default: 20, max: 100) |
after | String | Cursor for pagination |
Basic Example
Here's a simple example of querying for school information:
query {
school {
id
name
createdAt
}
}For more detailed examples and resource-specific queries, explore the resource pages linked above.
Pagination
The Loopwise Admin API uses cursor-based pagination to efficiently handle large datasets. This approach allows you to retrieve data in manageable chunks while maintaining consistent results across requests.
Pagination Structure
All paginated responses follow a consistent structure:
{
"data": {
"resourceName": {
"nodes": [
// Array of resource objects
],
"pageInfo": {
"hasNextPage": true,
"endCursor": "cursor-string"
}
}
}
}The key components are:
nodes: An array containing the requested resources for the current pagepageInfo: Metadata about the current page and navigationhasNextPage: Boolean indicating if more results exist beyond this pageendCursor: A string cursor that can be used to fetch the next page
Pagination Parameters
When querying paginated resources, you can use these parameters:
| Parameter | Type | Description |
|---|---|---|
first | Int | Number of items to return (default: 20, max: 100) |
after | String | Cursor string from a previous query's endCursor |
Pagination Example
Initial Query
To fetch the first page of courses:
query {
courses(first: 10) {
nodes {
id
name
description
}
pageInfo {
hasNextPage
endCursor
}
}
}Subsequent Pages
To fetch the next page, use the endCursor from the previous response:
query {
courses(first: 10, after: "previous-end-cursor") {
nodes {
id
name
description
}
pageInfo {
hasNextPage
endCursor
}
}
}JavaScript Pagination Example
Here's how to implement pagination in JavaScript:
async function fetchAllCourses(apiKey) {
const endpoint = 'https://teachify.io/admin/graphql';
let hasNextPage = true;
let after = null;
let allCourses = [];
while (hasNextPage) {
const query = `
query Courses($first: Int, $after: String) {
courses(first: 25, after: $after) {
nodes {
id
name
description
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Teachify-API-Key': apiKey
},
body: JSON.stringify({
query,
variables: { first: 25, after }
})
});
const result = await response.json();
const { nodes, pageInfo } = result.data.courses;
allCourses = [...allCourses, ...nodes];
hasNextPage = pageInfo.hasNextPage;
after = pageInfo.endCursor;
console.log(`Fetched ${nodes.length} courses. Total so far: ${allCourses.length}`);
}
return allCourses;
}Pagination Best Practices
-
Use reasonable page sizes: Request only what you need. Smaller page sizes (10-25 items) are better for interactive UIs, while larger sizes (50-100) may be more efficient for data processing.
-
Always check
hasNextPage: Don't assume there are more pages based on the number of items returned. -
Store the
endCursor: Save the cursor between user interactions or application states to maintain pagination position. -
Handle empty results: Your code should gracefully handle cases where no results are returned.
-
Avoid fetching all pages at once: For very large datasets, consider implementing "load more" or traditional page navigation rather than automatically loading all pages.
Filtering
The Loopwise Admin API supports powerful filtering capabilities that allow you to narrow down query results to exactly what you need. Filtering is performed on the server side, which improves performance by reducing the amount of data transferred.
Filter Structure
Filters are provided as input objects to queries. Each resource type has its own filter input type with fields specific to that resource. For example:
CourseFilterfor filtering coursesStudentFilterfor filtering studentsAssignmentFilterfor filtering assignments
Common Filter Types
String Filters
String fields typically support these filtering operations:
| Operation | Description | Example |
|---|---|---|
equals | Exact match | { name: { equals: "Math 101" } } |
contains | Contains substring | { name: { contains: "Math" } } |
startsWith | Starts with substring | { name: { startsWith: "Math" } } |
endsWith | Ends with substring | { name: { endsWith: "101" } } |
Number Filters
Number fields support range operations:
| Operation | Description | Example |
|---|---|---|
equals | Exact match | { enrollmentCount: { equals: 25 } } |
gt | Greater than | { enrollmentCount: { gt: 20 } } |
gte | Greater than or equal | { enrollmentCount: { gte: 20 } } |
lt | Less than | { enrollmentCount: { lt: 30 } } |
lte | Less than or equal | { enrollmentCount: { lte: 30 } } |
between | Between two values | { enrollmentCount: { between: [20, 30] } } |
Date Filters
Date fields support similar operations to number fields:
| Operation | Description | Example |
|---|---|---|
equals | Exact date match | { startDate: { equals: "2023-09-01" } } |
before | Before date | { startDate: { before: "2023-09-01" } } |
after | After date | { startDate: { after: "2023-09-01" } } |
between | Between two dates | { startDate: { between: ["2023-09-01", "2023-12-31"] } } |
Boolean Filters
Boolean fields can be filtered directly:
{
isActive: true
}ID Filters
ID fields support exact match or inclusion in a list:
| Operation | Description | Example |
|---|---|---|
equals | Exact ID match | { id: { equals: "course-123" } } |
in | ID in list | { id: { in: ["course-123", "course-456"] } } |
Combining Filters
You can combine multiple filters in a single query. By default, all conditions must be met (AND logic):
query {
courses(
filter: {
name: { contains: "Math" }
startDate: { after: "2023-01-01" }
enrollmentCount: { gt: 10 }
}
) {
nodes {
id
name
}
}
}Logical Operators
For more complex filtering, you can use logical operators:
AND
query {
courses(
filter: {
AND: [
{ name: { contains: "Math" } },
{ enrollmentCount: { gt: 10 } }
]
}
) {
nodes {
id
name
}
}
}OR
query {
courses(
filter: {
OR: [
{ name: { contains: "Math" } },
{ name: { contains: "Science" } }
]
}
) {
nodes {
id
name
}
}
}NOT
query {
courses(
filter: {
NOT: {
name: { contains: "Archived" }
}
}
) {
nodes {
id
name
}
}
}Filtering on Related Resources
You can filter based on related resources. For example, finding courses with specific instructors:
query {
courses(
filter: {
instructors: {
some: {
name: { contains: "Smith" }
}
}
}
) {
nodes {
id
name
}
}
}Resource-Specific Filters
Each resource type has specific filter fields. For detailed information on available filters for each resource, see the resource-specific documentation:
Filtering Best Practices
-
Filter on the server: Always use API filtering instead of retrieving large datasets and filtering client-side.
-
Be specific: Use the most specific filter operations available to minimize data transfer.
-
Combine with pagination: Use filtering together with pagination for the most efficient queries.
-
Test complex filters: Complex logical combinations should be thoroughly tested to ensure they return the expected results.