Documentation

Everything you need to integrate with CrudApi โ€” laymen-friendly explanations, copy-paste examples, and zero jargon when we can avoid it.

๐Ÿš€ Quickstart (5 minutes)

Goal: register your first database and call it from curl.

Step 1 โ€” Open the admin console

Visit /admin and log in with the default credentials:

Username: admin Password: admin@123
Change this immediately in production. Go to /admin/adminusers after first login.

Step 2 โ€” Register your database

  1. Click Databases โ†’ + Register Database
  2. Pick engine: MySQL (only MySQL today; SQL Server / PostgreSQL on roadmap)
  3. Fill in host, port, db name, user, password
  4. Click ๐Ÿ”Œ Test Connection โ€” green = ready, red shows the real error
  5. Click Register โ€” your db is live

Step 3 โ€” Create an API key

  1. Go to API Clients โ†’ + Create API Client
  2. Bind it to the database you just registered
  3. Pick a role: Reader (read-only), Editor (full CRUD), or any custom role
  4. Copy the API key โ€” you only see it once. Format: drk_abc123...

Step 4 โ€” Call your data

curl https://yourhost.com/api/v1/your_db_key/crud/your_table \ -H "X-API-Key: drk_yourapikey..."

You'll get back the table contents as JSON. That's it โ€” no boilerplate, no schemas to define.

๐Ÿ— Architecture (the big picture)

CrudApi is built from independent packages. Each does one thing well:

PackageWhat it does
SqlConnectorTalks to your databases (MySQL today; pluggable for others). Handles CRUD, bulk import, transactions.
CrudAdminIdentity & access control: users, roles, permissions, audit, sessions, CORS. Ships the admin UI.
SqliteAdminStandalone SQLite browser for your .db files.
CrudApi (this host)The web app you're running. Wires the packages together with your own routes.
CrudApi.DocsThis help system and the landing page.

Request flow: Your call hits /api/v1/{db}/crud/{table} โ†’ CORS check โ†’ Auth (API key/Basic/JWT) โ†’ Tenant resolution โ†’ Permission check โ†’ Row policy filter โ†’ SqlConnector queries your database โ†’ JSON response. Audited at every step.

๐Ÿ” Authentication โ€” pick one

Every API request must authenticate. You have three options. Pick based on your use case:

MethodBest forHow to send
API Key Recommended Server-to-server, mobile apps, scripts X-API-Key: drk_abc123...
Basic Auth Quick testing, legacy clients Authorization: Basic base64(user:pass)
JWT Web apps, user-specific tokens with claims Authorization: Bearer eyJhbG...

How to get them

Layperson explanation: An API key is like a password your app remembers. JWT is like a temporary ID card with extra info baked in. Basic Auth sends your username + password every request โ€” easy but less secure.

๐Ÿ—บ URL structure

All API URLs follow this pattern:

/api/v1/{database}/crud/{table}[/{id}]
PartExampleWhat it means
{database}masterThe db_key you set when registering the database in Admin.
{table}customersAny table that exists in that database.
{id} (optional)42For GET/PUT/DELETE of a specific row.

HTTP verbs

VerbWhat it does
GET /crud/customersList rows (filterable, paginated)
GET /crud/customers/id/42Get one row
POST /crud/customersInsert a row
PUT /crud/customers/id/42Update a row
DELETE /crud/customers/id/42Delete a row

๐Ÿ“ก Sample requests (copy-paste)

List rows

curl "https://yourhost.com/api/v1/master/crud/customers?limit=10" \ -H "X-API-Key: drk_..."

Filter and sort

curl "https://yourhost.com/api/v1/master/crud/customers?filter=country%20eq%20'India'&orderby=created_at%20desc" \ -H "X-API-Key: drk_..."

Insert a row

curl -X POST "https://yourhost.com/api/v1/master/crud/customers" \ -H "X-API-Key: drk_..." \ -H "Content-Type: application/json" \ -d '{"name":"John Doe","email":"john@example.com","country":"India"}'

Update a row

curl -X PUT "https://yourhost.com/api/v1/master/crud/customers/id/42" \ -H "X-API-Key: drk_..." \ -H "Content-Type: application/json" \ -d '{"name":"Jane Doe"}'

Delete a row

curl -X DELETE "https://yourhost.com/api/v1/master/crud/customers/id/42" \ -H "X-API-Key: drk_..."

๐Ÿ” Filters & sorting (OData syntax)

The filter language is a subset of OData. Pass it via the ?filter= query parameter.

Operators

OperatorMeaningExample
eqequalsstatus eq 'active'
nenot equalsstatus ne 'deleted'
gt / gegreater / greater-or-equalage gt 21
lt / leless / less-or-equalprice le 100
and / orcombine conditionsage gt 21 and country eq 'India'
containssubstring matchcontains(name, 'John')

Sorting

?orderby=created_at desc ?orderby=name asc,created_at desc

Pagination

?limit=50&offset=100

Joins (for related tables)

?join=orders on customers.id=orders.customer_id

๐Ÿ“ฅ Bulk import

Upload CSV files to insert thousands of rows at once. Three modes:

  • File upload โ€” multipart form, ideal for one-off imports
  • Filter source โ€” copy rows from another table using a filter
  • API source โ€” pull rows from a 3rd-party API

File upload example

curl -X POST "https://yourhost.com/api/v1/master/bulk/upload/customers" \ -H "X-API-Key: drk_..." \ -F "file=@customers.csv"

CSV format (smart)

The CSV header can use annotations for advanced features:

Name,Email,Country|CountryId (map:Country.Id=Name),Status (enum:Active,Inactive) John,john@e.com,India,Active Jane,jane@e.com,USA,Active
  • Country|CountryId (map:Country.Id=Name) โ€” looks up "India" in Country table and stores the matching Id
  • Status (enum:Active,Inactive) โ€” rejects any other value

Errors

Failed rows are returned as a downloadable CSV โ€” fix and re-upload.

โŒ Error reference

All errors return JSON in this shape:

{ "error": "credential_invalid", "errorDescription": "The credential is not recognized..." }

Common error codes

CodeHTTPWhat it means / how to fix
unauthorized401No credential sent. Add X-API-Key or Authorization header.
credential_invalid401Wrong API key / password / token. Re-copy it from Admin.
credential_inactive401The key was revoked in Admin โ†’ API Clients. Reactivate or recreate.
credential_expired401Key passed its expiry date. Recreate.
database_forbidden403Credential not allowed for this database. Bind it or mark Global.
forbidden_action403Role doesn't grant this permission (e.g. trying to delete with Reader role).
row_policy_forbidden403Row-level policy denies this operation on this specific row.
database_unreachable503The target database server is down. Check Admin โ†’ Databases โ†’ Test.

๐Ÿงฐ Admin tasks (typical workflow)

  1. Day 1: Change default admin password at /admin/adminusers
  2. Register databases: /admin/databases
  3. Add CORS origins: Click CORS on each database card
  4. Create users (or just API keys): /admin/users or /admin/apiclients
  5. Assign roles: /admin/roles โ€” start with built-in Owner / Editor / Writer / Reader
  6. Set policies: Optional row-level filters at /admin/policies
  7. Watch audit logs: /admin/auditlogs

๐ŸŒ CORS (when your frontend is on a different domain)

If your web app calls CrudApi from app.example.com and your API is on api.example.com, the browser blocks it unless you allow that origin.

To allow an origin

  1. Go to /admin/databases
  2. Click CORS on the database card
  3. Add origin: https://app.example.com

Wildcards work too:

  • https://*.example.com โ€” any subdomain
  • * โ€” any origin (dangerous; OSS / public read-only APIs only)
Server-to-server calls (curl, mobile apps) don't need CORS. CORS is purely a browser thing.

๐Ÿ›ก Row-level policies

Filter what rows a user can see/touch. Common example: "users in role 'IndiaTeam' can only see customers where country = India".

Configure at /admin/policies

  1. Pick a role
  2. Pick a table
  3. Pick an action (read / create / update / delete)
  4. Enter a filter JSON: {"country": "India"}

Now every request from that role automatically gets country='India' appended to its WHERE clause. Server-enforced, can't be bypassed.

๐Ÿ“œ Audit logs

Every API call is logged with: timestamp, actor (which API key / user), resource, action, outcome, IP, and request details.

View at /admin/auditlogs โ€” filter by event type, severity, or actor.

Configure retention at /admin/settings โ†’ Audit Configuration.

โš™ Runtime settings

Most behaviors are tunable from /admin/settings without restarting. Examples:

  • JWT expiry time
  • API key default lifetime
  • Password policy
  • Audit log retention
  • Max concurrent admin sessions

Host-app settings (bulk size, GitHub token, AI key) live at /admin/hostsettings.

๐Ÿณ Run with Docker

Easiest way to run CrudApi:

docker run -d -p 8080:80 \ -v $(pwd)/data:/app/Data \ --name crudapi \ ghcr.io/yourorg/crudapi:latest

Or with docker-compose.yml:

version: "3.8" services: crudapi: image: ghcr.io/yourorg/crudapi:latest ports: - "8080:80" volumes: - ./data:/app/Data environment: - ASPNETCORE_URLS=http://+:80 restart: unless-stopped

Then visit http://localhost:8080.

๐Ÿ”‘ Environment variables

Override appsettings.json using env vars. Use double underscore __ for nesting.

VariableDefaultNotes
ASPNETCORE_URLShttp://+:80Port the app listens on
Docs__ProductNameCrudApiBranding
Docs__GithubUrlโ€”Shown in nav + footer
Docs__EnableLandingtrueSet false to redirect / to admin

๐Ÿ”’ HTTPS & reverse proxies

In production, run CrudApi behind a reverse proxy (nginx, Caddy, Traefik) that terminates TLS and forwards HTTP internally. CrudApi auto-trusts X-Forwarded-* headers so URLs in responses reflect the public hostname.

Sample Caddy config:

api.example.com { reverse_proxy localhost:8080 }