DEV Community

Alex Spinov
Alex Spinov

Posted on

Directus Has a Free API You Should Know About

Directus wraps any SQL database with an instant REST and GraphQL API — no migration needed, works with your existing schema.

Instant API from Existing Database

Connect Directus to your PostgreSQL/MySQL/SQLite and get:

# REST API — auto-generated for every table
GET /items/posts?filter[status][_eq]=published&sort=-date_created&limit=10&fields=id,title,content,author.name

# GraphQL — also auto-generated
query {
  posts(filter: { status: { _eq: "published" } }, sort: ["-date_created"], limit: 10) {
    id
    title
    content
    author { name }
  }
}
Enter fullscreen mode Exit fullscreen mode

JavaScript SDK

import { createDirectus, rest, readItems, createItem, updateItem } from '@directus/sdk'

const client = createDirectus('https://your-directus.com').with(rest())

// Read
const posts = await client.request(
  readItems('posts', {
    filter: { status: { _eq: 'published' } },
    sort: ['-date_created'],
    limit: 10,
    fields: ['id', 'title', { author: ['name', 'avatar'] }]
  })
)

// Create
const newPost = await client.request(
  createItem('posts', {
    title: 'New Post',
    content: 'Content here',
    status: 'draft'
  })
)

// Update
await client.request(
  updateItem('posts', newPost.id, { status: 'published' })
)
Enter fullscreen mode Exit fullscreen mode

Real-Time via WebSocket

import { createDirectus, realtime } from '@directus/sdk'

const client = createDirectus('https://your-directus.com').with(realtime())

await client.connect()

client.onWebSocket('message', (data) => {
  if (data.type === 'subscription') {
    console.log('Change detected:', data.data)
  }
})

await client.subscribe('posts', {
  event: 'create',
  query: { fields: ['id', 'title'] }
})
Enter fullscreen mode Exit fullscreen mode

Flows — Visual Automation

Build automation visually in the admin panel:

  • Trigger: on item create/update/delete, schedule, webhook
  • Operations: send email, HTTP request, transform data, run script
  • Conditions: filter based on field values
// Custom operation (code)
module.exports = {
  id: 'send-slack',
  handler: async ({ data }, { services, getSchema }) => {
    await fetch(process.env.SLACK_WEBHOOK, {
      method: 'POST',
      body: JSON.stringify({ text: `New post: ${data.title}` })
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

Role-Based Access Control

// Granular permissions per collection, per action, per field
{
  "role": "editor",
  "collection": "posts",
  "action": "update",
  "permissions": { "author": { "_eq": "$CURRENT_USER" } }, // Only own posts
  "fields": ["title", "content", "tags"], // Can't change status or author
  "validation": { "title": { "_regex": "^[A-Z]" } } // Title must start with capital
}
Enter fullscreen mode Exit fullscreen mode

Real-World Use Case

A company had a legacy MySQL database with 50 tables and no API. Options: build Express routes for each table (months) or use Directus. They connected Directus to their existing database: instant API for all 50 tables, admin panel for non-developers, granular permissions. No migration, no schema changes, working in 1 hour.

Directus turns your database into an API without changing a single table.


Build Smarter Data Pipelines

Need to scrape websites, extract APIs, or automate data collection? Check out my ready-to-use scrapers on Apify — no coding required.

Custom scraping solution? Email me at spinov001@gmail.com — fast turnaround, fair prices.

Top comments (0)