# Plainbase > Plainbase is a simple backend for apps: tables of records, file uploads, email-code login for your app's customers, and one API key. It is built on Postgres, based in the UK/Europe, and you can export your data at any time. This file is for AI coding tools. Read it fully before writing code that talks to Plainbase. Base URL: https://plainbase.co.uk ## Before you start - Ask the user for their Plainbase secret API key. Never invent one. - Keep the key in a server-side environment variable such as PLAINBASE_API_KEY. Never write it into browser code, mobile app code, a public repository, or logs. - Plainbase tables are addressed by id, not by name. List tables first (GET /api/tables) to get the ids. - The user's project id is shown in the dashboard under "Authentication" -> "Use this in your app". You need it only for customer login. ## Authentication - Server code: send the header "x-api-key: ". - Customers signed in to the user's app: send "Authorization: Bearer " (see Customer login). Do not send both headers together. - A request with "x-api-key" that comes from a web page (it has an Origin header) is always refused with a 401 that explains why, and the key is flagged in the dashboard as possibly public. Never put the secret key in browser code. For web pages use customer login (Bearer token) or Public read tables. ## Tables and records - GET https://plainbase.co.uk/api/tables : list tables, with their records. - POST https://plainbase.co.uk/api/tables : create a table. Body: {"name":"Customers","fields":[{"name":"Name","type":"text"},{"name":"Email","type":"text"}]}. Field types: text, number, date, checkbox. Up to 30 fields. Tables made with a secret key start as Private. - GET https://plainbase.co.uk/api/tables/{tableId} : one table. - PATCH https://plainbase.co.uk/api/tables/{tableId} : rename a table or change its fields. - DELETE https://plainbase.co.uk/api/tables/{tableId} : NOT allowed with an API key (returns 403). Whole tables can only be deleted by the project owner in the dashboard, and can be undone for 30 days in Dashboard -> History. - GET https://plainbase.co.uk/api/tables/{tableId}/rows : list records. Each record has an id, a "data" object, and createdAt. - POST https://plainbase.co.uk/api/tables/{tableId}/rows : add a record. Body: {"data":{"Name":"Sam","Email":"sam@example.com"}}. Use the field names exactly as the table has them. - PATCH https://plainbase.co.uk/api/tables/{tableId}/rows/{rowId} : change a record. Body: {"data":{"Name":"New name"}}. Only the fields you send are changed. - DELETE https://plainbase.co.uk/api/tables/{tableId}/rows/{rowId} : deletes one record. The project owner can undo this for 30 days in Dashboard -> History, but do not rely on that. Send "content-type: application/json" on requests with a body. Table access settings (set by the project owner in the dashboard): - Private: only the dashboard and secret keys. - Logged-in users: customers who have signed in to the app (not secret keys). - Public read: anyone can read, nobody can write from outside. ## Customer login (email code, no passwords) 1. POST https://plainbase.co.uk/api/app-auth/{projectId}/request-code with {"email":"customer@example.com"}. A 6-digit code is emailed. It expires after 10 minutes and works once. 2. POST https://plainbase.co.uk/api/app-auth/{projectId}/verify-code with {"email":"customer@example.com","code":"123456"}. The reply includes {"user", "token", "expiresAt"}. 3. Send the token as "Authorization: Bearer " on later requests. GET https://plainbase.co.uk/api/app-auth/{projectId}/current-user shows who is signed in. POST https://plainbase.co.uk/api/app-auth/{projectId}/sign-out signs out. Login must be switched on first: Dashboard -> Authentication. ## Other - Export all data: GET https://plainbase.co.uk/api/export?format=csv or ?format=json (works with a secret key). - Files can be uploaded in the dashboard. A public file download API is planned, not available yet. ## Example (server-side JavaScript) const res = await fetch("https://plainbase.co.uk/api/tables/" + tableId + "/rows", { method: "POST", headers: { "x-api-key": process.env.PLAINBASE_API_KEY, "content-type": "application/json" }, body: JSON.stringify({ data: { Name: "Sam", Email: "sam@example.com" } }) }); if (!res.ok) throw new Error(await res.text()); // errors are plain text that explain the fix ## Rules for AI tools (please follow these) - Never delete a table, a record, or a column unless the user clearly asked for that in this conversation. Deleting a table or column cannot be undone. Edits and deletions of single records are recorded in Dashboard -> History for 30 days, but that is a safety net, not permission. - Before changing a table's structure (renaming, removing or retyping fields), tell the user what will change and wait for a yes. - Never make a table "Public read" or put a secret key in front-end code unless the user explicitly asks. - If a request fails, read the error text. It says what to change. Do not retry the same request in a loop. - Do not guess field names or ids. List the tables first. - You may be given an "AI key". It can be read-only or limited to some tables, and it can never delete, change tables, export or use files. If a request is refused with 403, tell the user. Do not look for a way around it. - If you are unsure, ask the user. ## Free plan limits 1 project, 3 tables, 1,000 records, 100 MB of files, 1 API key. If a request fails with "reached the Free limit", tell the user instead of trying to work around it. Paid plans: Starter and Pro (see https://plainbase.co.uk/pricing).