Data Service Quickstart
Get up and running with the Taruvi Data Service in minutes. This guide walks you through creating a complete blog application from scratch.
What You'll Build
A simple blog with:
- 👤 Users: Author accounts
- 📝 Posts: Blog articles
- 💬 Comments: User comments on posts
- 🏷️ Tags: Post categorization
Prerequisites
- ✅ Taruvi account with API access
- ✅ JWT authentication token
- ✅ Basic understanding of REST APIs
- ✅ curl, Postman, or similar HTTP client
Step 1: Create Your App
First, create an app to hold your blog data:
curl -X POST https://your-domain.com/api/apps/ \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My Blog",
"description": "A simple blogging platform"
}'
Response:
{
"id": 1,
"name": "My Blog",
"slug": "my-blog",
"description": "A simple blogging platform",
"created_at": "2024-01-15T10:30:00Z"
}
Save the slug value (my-blog) - you'll use it in all future requests.
Step 2: Import Your Schema
Create a file called blog-schema.json with your complete database schema:
{
"name": "blog-schema",
"title": "Blog Database Schema",
"description": "Complete blog application schema",
"resources": [
{
"name": "users",
"title": "User Accounts",
"schema": {
"fields": [
{
"name": "id",
"type": "integer",
"constraints": {"required": true}
},
{
"name": "username",
"type": "string",
"constraints": {"required": true, "maxLength": 50}
},
{
"name": "email",
"type": "string",
"format": "email",
"constraints": {"required": true}
},
{
"name": "bio",
"type": "string"
},
{
"name": "created_at",
"type": "datetime"
}
],
"primaryKey": ["id"]
}
},
{
"name": "posts",
"title": "Blog Posts",
"schema": {
"fields": [
{
"name": "id",
"type": "integer",
"constraints": {"required": true}
},
{
"name": "author_id",
"type": "integer",
"constraints": {"required": true}
},
{
"name": "title",
"type": "string",
"constraints": {"required": true, "maxLength": 200}
},
{
"name": "content",
"type": "string",
"constraints": {"required": true}
},
{
"name": "excerpt",
"type": "string"
},
{
"name": "published_at",
"type": "datetime"
},
{
"name": "status",
"type": "string",
"constraints": {
"required": true,
"enum": ["draft", "published", "archived"]
}
}
],
"primaryKey": ["id"],
"foreignKeys": [
{
"fields": ["author_id"],
"reference": {
"resource": "users",
"fields": ["id"]
}
}
]
}
},
{
"name": "comments",
"title": "Post Comments",
"schema": {
"fields": [
{
"name": "id",
"type": "integer",
"constraints": {"required": true}
},
{
"name": "post_id",
"type": "integer",
"constraints": {"required": true}
},
{
"name": "user_id",
"type": "integer",
"constraints": {"required": true}
},
{
"name": "content",
"type": "string",
"constraints": {"required": true}
},
{
"name": "created_at",
"type": "datetime"
}
],
"primaryKey": ["id"],
"foreignKeys": [
{
"fields": ["post_id"],
"reference": {
"resource": "posts",
"fields": ["id"]
}
},
{
"fields": ["user_id"],
"reference": {
"resource": "users",
"fields": ["id"]
}
}
]
}
},
{
"name": "tags",
"title": "Post Tags",
"schema": {
"fields": [
{
"name": "id",
"type": "integer",
"constraints": {"required": true}
},
{
"name": "name",
"type": "string",
"constraints": {"required": true, "maxLength": 50}
},
{
"name": "slug",
"type": "string",
"constraints": {"required": true, "maxLength": 50}
}
],
"primaryKey": ["id"]
}
},
{
"name": "post_tags",
"title": "Post-Tag Relationships",
"schema": {
"fields": [
{
"name": "post_id",
"type": "integer",
"constraints": {"required": true}
},
{
"name": "tag_id",
"type": "integer",
"constraints": {"required": true}
}
],
"primaryKey": ["post_id", "tag_id"],
"foreignKeys": [
{
"fields": ["post_id"],
"reference": {
"resource": "posts",
"fields": ["id"]
}
},
{
"fields": ["tag_id"],
"reference": {
"resource": "tags",
"fields": ["id"]
}
}
]
}
}
]
}
Now import it with automatic table creation:
curl -X POST "https://your-domain.com/api/apps/my-blog/datatables/create_schema/?materialize=true" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d @blog-schema.json
Response:
{
"created_count": 5,
"error_count": 0,
"created_tables": [
{"id": 1, "name": "users", "is_materialized": true, "field_count": 5},
{"id": 2, "name": "posts", "is_materialized": true, "field_count": 7},
{"id": 3, "name": "comments", "is_materialized": true, "field_count": 5},
{"id": 4, "name": "tags", "is_materialized": true, "field_count": 3},
{"id": 5, "name": "post_tags", "is_materialized": true, "field_count": 2}
],
"errors": [],
"materialized": true
}
✅ All 5 tables created and ready to use!
Step 3: Create Some Users
- REST API
- Python
- JavaScript
curl -X POST https://your-domain.com/api/apps/my-blog/datatables/users/data/ \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '[
{
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"bio": "Software developer and tech blogger",
"created_at": "2024-01-15T10:00:00Z"
},
{
"id": 2,
"username": "jane_smith",
"email": "jane@example.com",
"bio": "Product designer and UX enthusiast",
"created_at": "2024-01-16T09:30:00Z"
}
]'
# Bulk create users
users = auth_client.database.create('users', [
{
'id': 1,
'username': 'john_doe',
'email': 'john@example.com',
'bio': 'Software developer and tech blogger',
'created_at': '2024-01-15T10:00:00Z'
},
{
'id': 2,
'username': 'jane_smith',
'email': 'jane@example.com',
'bio': 'Product designer and UX enthusiast',
'created_at': '2024-01-16T09:30:00Z'
}
], app_slug='my-blog')
print(f"Created {len(users['data'])} users")
for user in users['data']:
print(f"- {user['username']} ({user['email']})")
// Bulk create users
const users = await client.database
.from('users')
.create([
{
id: 1,
username: 'john_doe',
email: 'john@example.com',
bio: 'Software developer and tech blogger',
created_at: '2024-01-15T10:00:00Z'
},
{
id: 2,
username: 'jane_smith',
email: 'jane@example.com',
bio: 'Product designer and UX enthusiast',
created_at: '2024-01-16T09:30:00Z'
}
])
.execute()
console.log(`Created ${users.data.length} users`)
users.data.forEach(user => {
console.log(`- ${user.username} (${user.email})`)
})
Step 4: Create Blog Posts
- REST API
- Python
- JavaScript
curl -X POST https://your-domain.com/api/apps/my-blog/datatables/posts/data/ \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '[
{
"id": 1,
"author_id": 1,
"title": "Getting Started with Taruvi",
"content": "In this post, we will explore the powerful features of Taruvi...",
"excerpt": "Learn the basics of Taruvi Data Service",
"status": "published",
"published_at": "2024-01-15T12:00:00Z"
},
{
"id": 2,
"author_id": 1,
"title": "Advanced Querying Techniques",
"content": "Taruvi provides powerful query capabilities including...",
"excerpt": "Master advanced filtering and population",
"status": "published",
"published_at": "2024-01-16T14:00:00Z"
},
{
"id": 3,
"author_id": 2,
"title": "Designing Data-Driven UIs",
"content": "When building interfaces powered by Taruvi...",
"excerpt": "Best practices for UI design",
"status": "draft",
"published_at": null
}
]'
# Create posts with foreign key relationships (author_id)
posts = auth_client.database.create('posts', [
{
'id': 1,
'author_id': 1,
'title': 'Getting Started with Taruvi',
'content': 'In this post, we will explore the powerful features of Taruvi...',
'excerpt': 'Learn the basics of Taruvi Data Service',
'status': 'published',
'published_at': '2024-01-15T12:00:00Z'
},
{
'id': 2,
'author_id': 1,
'title': 'Advanced Querying Techniques',
'content': 'Taruvi provides powerful query capabilities including...',
'excerpt': 'Master advanced filtering and population',
'status': 'published',
'published_at': '2024-01-16T14:00:00Z'
},
{
'id': 3,
'author_id': 2,
'title': 'Designing Data-Driven UIs',
'content': 'When building interfaces powered by Taruvi...',
'excerpt': 'Best practices for UI design',
'status': 'draft',
'published_at': None
}
], app_slug='my-blog')
print(f"Created {len(posts['data'])} posts")
// Create posts with foreign key relationships (author_id)
const posts = await client.database
.from('posts')
.create([
{
id: 1,
author_id: 1,
title: 'Getting Started with Taruvi',
content: 'In this post, we will explore the powerful features of Taruvi...',
excerpt: 'Learn the basics of Taruvi Data Service',
status: 'published',
published_at: '2024-01-15T12:00:00Z'
},
{
id: 2,
author_id: 1,
title: 'Advanced Querying Techniques',
content: 'Taruvi provides powerful query capabilities including...',
excerpt: 'Master advanced filtering and population',
status: 'published',
published_at: '2024-01-16T14:00:00Z'
},
{
id: 3,
author_id: 2,
title: 'Designing Data-Driven UIs',
content: 'When building interfaces powered by Taruvi...',
excerpt: 'Best practices for UI design',
status: 'draft',
published_at: null
}
])
.execute()
console.log(`Created ${posts.data.length} posts`)
Step 5: Add Some Comments
- REST API
- Python
- JavaScript
curl -X POST https://your-domain.com/api/apps/my-blog/datatables/comments/data/ \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '[
{
"id": 1,
"post_id": 1,
"user_id": 2,
"content": "Great introduction! Very helpful for beginners.",
"created_at": "2024-01-15T14:20:00Z"
},
{
"id": 2,
"post_id": 1,
"user_id": 1,
"content": "Thanks! Glad you found it useful.",
"created_at": "2024-01-15T15:30:00Z"
},
{
"id": 3,
"post_id": 2,
"user_id": 2,
"content": "The populate feature is amazing!",
"created_at": "2024-01-16T16:00:00Z"
}
]'
# Create comments with relationships to posts and users
comments = auth_client.database.create('comments', [
{
'id': 1,
'post_id': 1,
'user_id': 2,
'content': 'Great introduction! Very helpful for beginners.',
'created_at': '2024-01-15T14:20:00Z'
},
{
'id': 2,
'post_id': 1,
'user_id': 1,
'content': 'Thanks! Glad you found it useful.',
'created_at': '2024-01-15T15:30:00Z'
},
{
'id': 3,
'post_id': 2,
'user_id': 2,
'content': 'The populate feature is amazing!',
'created_at': '2024-01-16T16:00:00Z'
}
], app_slug='my-blog')
print(f"Created {len(comments['data'])} comments")
// Create comments with relationships to posts and users
const comments = await client.database
.from('comments')
.create([
{
id: 1,
post_id: 1,
user_id: 2,
content: 'Great introduction! Very helpful for beginners.',
created_at: '2024-01-15T14:20:00Z'
},
{
id: 2,
post_id: 1,
user_id: 1,
content: 'Thanks! Glad you found it useful.',
created_at: '2024-01-15T15:30:00Z'
},
{
id: 3,
post_id: 2,
user_id: 2,
content: 'The populate feature is amazing!',
created_at: '2024-01-16T16:00:00Z'
}
])
.execute()
console.log(`Created ${comments.data.length} comments`)
Step 6: Query Your Data
List All Published Posts
- REST API
- Python
- JavaScript
curl "https://your-domain.com/api/apps/my-blog/datatables/posts/data/?status=published" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Query published posts using filter
published_posts = auth_client.database.query('posts', app_slug='my-blog') \
.filter('status', 'eq', 'published') \
.get()
print(f"Found {len(published_posts)} published posts")
for post in published_posts:
print(f"- {post['title']}")
// Query published posts using filter
const publishedPosts = await client.database
.from('posts')
.filter('status', 'eq', 'published')
.execute()
console.log(`Found ${publishedPosts.data.length} published posts`)
publishedPosts.data.forEach(post => {
console.log(`- ${post.title}`)
})
Get Posts with Authors
- REST API
- Python
- JavaScript
curl "https://your-domain.com/api/apps/my-blog/datatables/posts/data/?populate=author" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Get posts and populate author relationship
posts_with_authors = auth_client.database.query('posts', app_slug='my-blog') \
.populate('author') \
.get()
for post in posts_with_authors:
author = post.get('author', {})
print(f"{post['title']} by {author.get('username', 'Unknown')}")
// Get posts and populate author relationship
const postsWithAuthors = await client.database
.from('posts')
.populate(['author'])
.execute()
postsWithAuthors.data.forEach(post => {
const author = post.author || {}
console.log(`${post.title} by ${author.username || 'Unknown'}`)
})
Response:
{
"data": [
{
"id": 1,
"author_id": 1,
"title": "Getting Started with Taruvi",
"status": "published",
"author": {
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"bio": "Software developer and tech blogger"
}
},
{
"id": 2,
"author_id": 1,
"title": "Advanced Querying Techniques",
"status": "published",
"author": {
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"bio": "Software developer and tech blogger"
}
}
],
"total": 2
}
Get Single Post with Full Details
curl "https://your-domain.com/api/apps/my-blog/datatables/posts/data/1/?populate=author,comments.user" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Response:
{
"data": {
"id": 1,
"title": "Getting Started with Taruvi",
"content": "In this post, we will explore...",
"excerpt": "Learn the basics of Taruvi Data Service",
"status": "published",
"published_at": "2024-01-15T12:00:00Z",
"author": {
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"bio": "Software developer and tech blogger"
},
"comments": [
{
"id": 1,
"content": "Great introduction! Very helpful for beginners.",
"created_at": "2024-01-15T14:20:00Z",
"user": {
"id": 2,
"username": "jane_smith",
"email": "jane@example.com"
}
},
{
"id": 2,
"content": "Thanks! Glad you found it useful.",
"created_at": "2024-01-15T15:30:00Z",
"user": {
"id": 1,
"username": "john_doe",
"email": "john@example.com"
}
}
]
}
}
Search Posts
curl "https://your-domain.com/api/apps/my-blog/datatables/posts/data/?title_contains=taruvi&status=published" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Get User's Posts
curl "https://your-domain.com/api/apps/my-blog/datatables/posts/data/?author_id=1&_sort=published_at&_order=desc" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Paginate Results
curl "https://your-domain.com/api/apps/my-blog/datatables/posts/data/?status=published&_start=0&_end=10" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Step 7: Update Data
Update a Post
- REST API
- Python
- JavaScript
curl -X PATCH https://your-domain.com/api/apps/my-blog/datatables/posts/data/3/ \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "published",
"published_at": "2024-01-17T10:00:00Z"
}'
# Update a single post
updated_post = auth_client.database.update('posts', 3, {
'status': 'published',
'published_at': '2024-01-17T10:00:00Z'
}, app_slug='my-blog')
print(f"Updated post: {updated_post['data']['title']}")
print(f"Status: {updated_post['data']['status']}")
// Update a single post
const updatedPost = await client.database
.from('posts')
.get('3')
.update({
status: 'published',
published_at: '2024-01-17T10:00:00Z'
})
.execute()
console.log(`Updated post: ${updatedPost.data.title}`)
console.log(`Status: ${updatedPost.data.status}`)
Update a User's Bio
curl -X PATCH https://your-domain.com/api/apps/my-blog/datatables/users/data/1/ \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bio": "Senior software developer and technical writer"
}'
Step 8: Delete Data
Delete a Comment
- REST API
- Python
- JavaScript
curl -X DELETE https://your-domain.com/api/apps/my-blog/datatables/comments/data/3/ \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Delete a comment
auth_client.database.delete('comments', 3, app_slug='my-blog')
print("Comment deleted successfully")
// Delete a comment
await client.database
.from('comments')
.delete('3')
.execute()
console.log("Comment deleted successfully")
Step 9: Aggregation Queries
Use aggregations for analytics and reporting without fetching all data:
Aggregations are REST API only. The Python and JavaScript SDKs do not currently support _aggregate, _group_by, or _having parameters. For analytics queries, use the REST API directly or fetch records and aggregate client-side.
Count Posts by Author
- REST API
- Python
- JavaScript
curl "https://your-domain.com/api/apps/my-blog/datatables/posts/data/?_aggregate=count(*)&_group_by=author_id&populate=author" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Note: Aggregations not supported in SDK
# Workaround: Fetch all records and aggregate client-side
posts = auth_client.database.query('posts', app_slug='my-blog') \
.populate('author') \
.get()
# Count posts by author using Python
from collections import Counter
author_counts = Counter(post['author_id'] for post in posts if 'author_id' in post)
for author_id, count in author_counts.items():
# Find author info
author = next((p['author'] for p in posts if p.get('author_id') == author_id and 'author' in p), None)
if author:
print(f"{author['username']}: {count} posts")
Limitation: This approach fetches all records into memory. For large datasets, use the REST API directly.
// Note: Aggregations not supported in SDK
// Workaround: Fetch all records and aggregate client-side
const posts = await client.database
.from('posts')
.populate(['author'])
.execute()
// Count posts by author using JavaScript
const authorCounts = posts.data.reduce((acc, post) => {
const authorId = post.author_id
acc[authorId] = (acc[authorId] || 0) + 1
return acc
}, {})
Object.entries(authorCounts).forEach(([authorId, count]) => {
const post = posts.data.find(p => p.author_id == authorId)
if (post && post.author) {
console.log(`${post.author.username}: ${count} posts`)
}
})
Limitation: This approach fetches all records into memory. For large datasets, use the REST API directly.
Response:
{
"data": [
{
"author_id": 1,
"author": {
"id": 1,
"username": "john_doe",
"email": "john@example.com"
},
"count": 2
},
{
"author_id": 2,
"author": {
"id": 2,
"username": "jane_smith",
"email": "jane@example.com"
},
"count": 1
}
],
"total": 2
}
Posts Per Day Statistics
curl "https://your-domain.com/api/apps/my-blog/datatables/posts/data/?_aggregate=count(*)&_group_by=date_trunc('day',published_at)&status=published" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Average Comments Per Post
curl "https://your-domain.com/api/apps/my-blog/datatables/comments/data/?_aggregate=count(*),avg(id)&_group_by=post_id" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Total Stats
curl "https://your-domain.com/api/apps/my-blog/datatables/posts/data/?_aggregate=count(*),count(distinct author_id)" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Response:
{
"data": [],
"aggregates": {
"count": 3,
"count_distinct_author_id": 2
}
}
See Aggregations Guide for advanced GROUP BY, HAVING, and more aggregate functions.
Step 10: Bulk Operations
Efficiently create, update, or delete multiple records at once:
Bulk Create Tags
- REST API
- Python
- JavaScript
curl -X POST https://your-domain.com/api/apps/my-blog/datatables/tags/data/ \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '[
{"id": 1, "name": "Python", "slug": "python"},
{"id": 2, "name": "Django", "slug": "django"},
{"id": 3, "name": "JavaScript", "slug": "javascript"},
{"id": 4, "name": "Tutorial", "slug": "tutorial"},
{"id": 5, "name": "Advanced", "slug": "advanced"}
]'
# Bulk create tags
tags = auth_client.database.create('tags', [
{'id': 1, 'name': 'Python', 'slug': 'python'},
{'id': 2, 'name': 'Django', 'slug': 'django'},
{'id': 3, 'name': 'JavaScript', 'slug': 'javascript'},
{'id': 4, 'name': 'Tutorial', 'slug': 'tutorial'},
{'id': 5, 'name': 'Advanced', 'slug': 'advanced'}
], app_slug='my-blog')
print(f"Created {len(tags['data'])} tags")
// Bulk create tags
const tags = await client.database
.from('tags')
.create([
{ id: 1, name: 'Python', slug: 'python' },
{ id: 2, name: 'Django', slug: 'django' },
{ id: 3, name: 'JavaScript', slug: 'javascript' },
{ id: 4, name: 'Tutorial', slug: 'tutorial' },
{ id: 5, name: 'Advanced', slug: 'advanced' }
])
.execute()
console.log(`Created ${tags.data.length} tags`)
Response:
{
"data": [
{"id": 1, "name": "Python", "slug": "python"},
{"id": 2, "name": "Django", "slug": "django"},
{"id": 3, "name": "JavaScript", "slug": "javascript"},
{"id": 4, "name": "Tutorial", "slug": "tutorial"},
{"id": 5, "name": "Advanced", "slug": "advanced"}
]
}
Bulk Update Post Status
Update multiple posts at once:
- REST API
- Python
- JavaScript
curl -X PATCH https://your-domain.com/api/apps/my-blog/datatables/posts/data/ \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '[
{"id": 1, "status": "archived"},
{"id": 2, "status": "archived"}
]'
# Bulk update post status
updated_posts = auth_client.database.update('posts', [
{'id': 1, 'status': 'archived'},
{'id': 2, 'status': 'archived'}
], app_slug='my-blog')
print(f"Updated {len(updated_posts['data'])} posts to archived")
// Bulk update post status
const updatedPosts = await client.database
.from('posts')
.update([
{ id: 1, status: 'archived' },
{ id: 2, status: 'archived' }
])
.execute()
console.log(`Updated ${updatedPosts.data.length} posts to archived`)
Upsert (Insert or Update)
Create new records or update existing ones based on unique fields:
curl -X POST "https://your-domain.com/api/apps/my-blog/datatables/tags/data/upsert/?unique_fields=slug" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '[
{"name": "Python Programming", "slug": "python"},
{"name": "React", "slug": "react"},
{"name": "TypeScript", "slug": "typescript"}
]'
If a tag with slug="python" exists, it updates the name. Otherwise, it creates a new tag.
Bulk Delete by Filter
Delete all draft posts older than 30 days:
- REST API
- Python
- JavaScript
curl -X DELETE "https://your-domain.com/api/apps/my-blog/datatables/posts/data/?filter={\"status\":\"draft\",\"created_at__lt\":\"2024-01-01\"}" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Response:
{
"deleted": 5
}
# Bulk delete by filter
result = auth_client.database.delete('posts', filter={
'status': 'draft',
'created_at__lt': '2024-01-01'
}, app_slug='my-blog')
print(f"Deleted {result['deleted']} draft posts")
// Bulk delete by filter is not supported in JavaScript SDK
// Workaround: Fetch matching records and delete individually
const draftPosts = await client.database
.from('posts')
.filter('status', 'eq', 'draft')
.filter('created_at', 'lt', '2024-01-01')
.execute()
let deletedCount = 0
for (const post of draftPosts.data) {
await client.database
.from('posts')
.delete(post.id.toString())
.execute()
deletedCount++
}
console.log(`Deleted ${deletedCount} draft posts`)
JavaScript SDK Limitation: Bulk delete by filter is not supported. Use the workaround above or call the REST API directly.
See CRUD Operations Guide for complete bulk operation documentation.
Common Patterns
Blog Homepage
Show recent published posts with authors:
curl "https://your-domain.com/api/apps/my-blog/datatables/posts/data/?\
status=published&\
populate=author&\
_sort=published_at&\
_order=desc&\
_start=0&\
_end=10" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Author Profile
Get author with their posts:
curl "https://your-domain.com/api/apps/my-blog/datatables/users/data/1/?\
populate=posts&\
posts_status=published&\
posts_sort=published_at&\
posts_order=desc" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Comment Count
Get total comments for monitoring:
curl "https://your-domain.com/api/apps/my-blog/datatables/comments/data/" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.total'
The response will include the total count:
{
"data": [...],
"total": 15
}
Next Steps
Deep Dive into Features
Now that you've built your first app, explore these comprehensive guides:
Core Operations
- CRUD Operations: Complete guide to creating, reading, updating, and deleting data
- Querying & Filtering: Master 20+ filter operators, sorting, and pagination
- Aggregations: SQL-like GROUP BY, HAVING, and aggregate functions
Advanced Topics
- Relationships: Foreign keys, JOINs, and relationship population
- Hierarchies: Tree structures and organizational charts
- Graph Traversal: Network queries with BFS/DFS algorithms
- Authorization: Policy-based access control with row-level security
Schema & Data Management
- Schema Guide: Detailed Frictionless Table Schema documentation
- Migrations: Schema evolution with Alembic
- Indexes: Create indexes for better performance
- Data Imports: Bulk data loading from CSV/JSON files
Build Something Real
Now that you've mastered the basics, try building:
- E-commerce Store: Products, orders, customers, reviews
- Project Management: Projects, tasks, users, comments
- CRM: Contacts, companies, deals, activities
- Social Network: Users, posts, follows, likes
Integration Examples
Check out our example integrations:
- React + TypeScript: Full-stack blog application
- Vue.js: E-commerce storefront
- Python Backend: Data aggregation service
- Mobile (React Native): Blog reader app
Troubleshooting
"Method POST not allowed"
Problem: Trying to create data at wrong endpoint
Solution: Add /data/ to the URL:
# ❌ Wrong
POST /api/apps/my-blog/datatables/posts/
# ✅ Correct
POST /api/apps/my-blog/datatables/posts/data/
"Table is not materialized"
Problem: Trying to insert data into unmaterialized table
Solution: Use ?materialize=true when importing schema, or materialize individually:
POST /api/apps/my-blog/datatables/posts/materialize/
Authentication Errors
Problem: Getting 401 Unauthorized
Solution: Check your JWT token:
# Get a new token
POST /api/auth/jwt/token/
{
"username": "your-username",
"password": "your-password"
}
Get Help
Happy coding! 🚀