Schema Import (for AI agents)¶
Apilane can bulk-import entities, properties, constraints, security rules and custom endpoints into an existing application from a single JSON document. This page is a precise specification of that JSON so an AI agent (or any automation) can generate a valid payload from scratch.
Open it in the Portal at Application → Import, paste the JSON into the JSON payload box, and click Import. (The same page can also pre-fill the payload by diffing another application — the Load from another application panel — which is a good way to see a real payload.)
How the import behaves¶
- Additive and idempotent. The import only ever creates what is missing. Existing entities, properties, constraints, security rules and custom endpoints are never modified or deleted.
- Existing items are validated, not overwritten. If an entity/property/security rule already exists, its metadata is compared against the payload. If it is identical, it is skipped (a warning is returned). If it differs, the whole import aborts with an error — nothing is half-applied for that mismatch.
- FK-dependency ordering is automatic. Entities are created in foreign-key dependency order, so you may list them in any order — a child entity may appear before the parent it references, as long as both are in the payload (or the parent already exists).
- System columns are added for you. When a new entity is created, Apilane automatically adds its system properties (
ID,Owner,Created, …). Never include them inProperties.
Top-level shape¶
{
"Entities": [],
"Security": [],
"CustomEndpoints": []
}
All three arrays are optional — include only what you want to import.
| Field | Type | Description |
|---|---|---|
Entities |
array | Entities to create, each with its properties and constraints |
Security |
array | Access-control rules (entity / custom endpoint / schema) |
CustomEndpoints |
array | Custom SQL endpoints |
Entities¶
{
"Name": "Product",
"Description": "Product catalog",
"RequireChangeTracking": false,
"HasDifferentiationProperty": false,
"Properties": [],
"Constraints": []
}
| Field | Type | Required | Description |
|---|---|---|---|
Name |
string | ✅ | Entity name. Becomes the table name and the entity used in the API. |
Description |
string | null | Free-text description. | |
RequireChangeTracking |
bool | ✅ | When true, Apilane keeps a history snapshot of a record's previous values on every update, plus a final snapshot on delete. |
HasDifferentiationProperty |
bool | ✅ | When true, the entity participates in the application's differentiation (multi-tenant) partitioning. Must match the target app's differentiation setup. |
Properties |
array | ✅ | User-defined properties (see below). Do not include system properties. |
Constraints |
array | Unique and foreign-key constraints (see below). |
Existing entity metadata must match
If an entity with the same name already exists, RequireChangeTracking and HasDifferentiationProperty must be identical to the payload or the import aborts. Its new properties/constraints are still processed and added.
Properties¶
{
"Name": "Price",
"TypeID": 2,
"Required": true,
"Minimum": 0,
"Maximum": null,
"DecimalPlaces": 2,
"Encrypted": false,
"ValidationRegex": null,
"Description": null
}
| Field | Type | Description |
|---|---|---|
Name |
string | Property (column) name. |
TypeID |
int | Data type — see the enum below. |
Required |
bool | true = NOT NULL. |
Minimum |
long | null | String: minimum length. Number: minimum value. Date: minimum (unix ms). Boolean: null. |
Maximum |
long | null | String: maximum length. Number: maximum value. Date: maximum (unix ms). Boolean: null. |
DecimalPlaces |
int | null | Number only. 0 = integer, 2 = two decimals, etc. null for non-numeric types. |
Encrypted |
bool | String only. Stores the value encrypted at rest. |
ValidationRegex |
string | null | String only. Server-side validation pattern. |
Description |
string | null | Free-text description. |
TypeID values (PropertyType):
TypeID |
Type |
|---|---|
1 |
String |
2 |
Number |
3 |
Boolean |
4 |
Date (stored as unix-milliseconds) |
Constraints¶
A constraint is { "TypeID": <int>, "Properties": "<string>" }. The Properties string is encoded differently per type.
TypeID |
Constraint | Properties format |
Example |
|---|---|---|---|
1 |
Unique | Comma-separated column name(s). One column, or several for a composite unique key. | "Email" · "FirstName,LastName" |
2 |
Foreign key | "LocalColumn,ReferencedEntity" or "LocalColumn,ReferencedEntity,OnDeleteLogic" |
"Product_ID,Product" · "Product_ID,Product,2" |
For a foreign key, first add a Number property to hold the reference (e.g. Product_ID), then add the FK constraint pointing at the referenced entity's name. The FK targets that entity's ID primary key.
On-delete logic (ForeignKeyLogic, the optional 3rd element; defaults to 0):
| Value | Behaviour |
|---|---|
0 |
On delete no action |
1 |
On delete set null |
2 |
On delete cascade |
Include IsSystem if you copy constraints verbatim
EntityConstraint also has an IsSystem flag. For hand-written imports leave it out (defaults to false) — you only ever create non-system constraints.
Security rules¶
Each entry is a DBWS_Security rule granting a role permission to perform an action on an entity, custom endpoint, or the schema.
{
"Name": "Product",
"TypeID": 0,
"RoleID": "ANONYMOUS",
"Action": "get",
"Record": 0,
"Properties": null,
"RateLimit": null
}
| Field | Type | Description |
|---|---|---|
Name |
string | The target: the entity name (for TypeID 0) or custom endpoint name (for TypeID 1). Empty for schema rules. |
TypeID |
int | What the rule targets — SecurityTypes below. |
RoleID |
string | The role this rule grants. ANONYMOUS, AUTHENTICATED, or a custom role name. |
Action |
string | get, post, put, or delete (lower-case). |
Record |
int | Record scope — All (0) or Owned (1). Applies to get/put/delete. |
Properties |
string | null | Comma-separated columns this rule grants for the action. The primary key is always included. null/empty grants no non-PK columns. |
RateLimit |
object | null | Optional rate limit (see below). |
TypeID values (SecurityTypes):
TypeID |
Target | Name holds |
Typical Action |
|---|---|---|---|
0 |
Entity | Entity name | get / post / put / delete |
1 |
Custom endpoint | Endpoint name | get |
2 |
Schema | (empty) | get |
Record values (EndpointRecordAuthorization):
| Value | Meaning |
|---|---|
0 |
All records |
1 |
Owned only — restricted to rows whose Owner equals the current user's ID |
Roles. Apilane always evaluates a user's custom roles plus the two built-ins:
RoleID |
Applies to |
|---|---|
ANONYMOUS |
Any request with no auth token |
AUTHENTICATED |
Any request with a valid auth token |
| (custom) | Users whose Roles property contains that role |
Rate limit (optional)¶
"RateLimit": { "MaxRequests": 100, "TimeWindowType": 2 }
| Field | Type | Description |
|---|---|---|
MaxRequests |
int | Max requests allowed within the window. |
TimeWindowType |
int | Window — EndpointRateLimit below. |
TimeWindowType |
Window |
|---|---|
1 |
Per second |
2 |
Per minute |
3 |
Per hour |
Property-level access
To let a role read some columns but write only others, add two rules with different Action and Properties — e.g. a get rule listing all readable columns and a put rule listing only the writable ones.
Custom endpoints¶
{
"Name": "GetAllProduct",
"Description": "Retrieves all products.",
"Query": "SELECT * FROM [Product];"
}
| Field | Type | Description |
|---|---|---|
Name |
string | Endpoint name (used in the API path). |
Description |
string | null | Free-text description. |
Query |
string | The SQL. Write it for your storage provider (SQLite / SQL Server / MySQL). Parameters are {ParamName} placeholders and are big-integer (long) only. Multiple ;-separated statements return multiple result sets. |
See Custom Endpoints for query authoring details. Importing a custom endpoint does not create a security rule for it — add a matching Security entry with TypeID: 1 to expose it.
Complete example¶
Creates a Product and OrderItem (with a foreign key to Product), makes Product readable by anonymous users, and adds a custom endpoint:
{
"Entities": [
{
"Name": "Product",
"Description": "Product catalog",
"RequireChangeTracking": false,
"HasDifferentiationProperty": false,
"Properties": [
{ "Name": "Title", "TypeID": 1, "Required": true, "Minimum": null, "Maximum": 200, "DecimalPlaces": null, "Encrypted": false, "ValidationRegex": null, "Description": null },
{ "Name": "Price", "TypeID": 2, "Required": true, "Minimum": 0, "Maximum": null, "DecimalPlaces": 2, "Encrypted": false, "ValidationRegex": null, "Description": null }
],
"Constraints": [
{ "TypeID": 1, "Properties": "Title" }
]
},
{
"Name": "OrderItem",
"Description": "Line item in an order",
"RequireChangeTracking": false,
"HasDifferentiationProperty": false,
"Properties": [
{ "Name": "Product_ID", "TypeID": 2, "Required": true, "Minimum": null, "Maximum": null, "DecimalPlaces": 0, "Encrypted": false, "ValidationRegex": null, "Description": null },
{ "Name": "Qty", "TypeID": 2, "Required": true, "Minimum": 1, "Maximum": null, "DecimalPlaces": 0, "Encrypted": false, "ValidationRegex": null, "Description": null }
],
"Constraints": [
{ "TypeID": 2, "Properties": "Product_ID,Product,2" }
]
}
],
"Security": [
{ "Name": "Product", "TypeID": 0, "RoleID": "ANONYMOUS", "Action": "get", "Record": 0, "Properties": "Title,Price", "RateLimit": { "MaxRequests": 100, "TimeWindowType": 2 } }
],
"CustomEndpoints": [
{ "Name": "GetAllProduct", "Description": "Retrieves all products.", "Query": "SELECT * FROM [Product];" }
]
}
Checklist for generating a payload¶
- [ ] Use the correct integer enums: property
TypeID(String=1, Number=2, Boolean=3, Date=4); constraintTypeID(Unique=1, FK=2); securityTypeID(Entity=0, CustomEndpoint=1, Schema=2). - [ ] Do not include system properties (
ID,Owner,Created) — they are added automatically. - [ ] Foreign keys: add a
Numberproperty to hold the reference, then a constraint"LocalColumn,ReferencedEntity[,OnDeleteLogic]". - [ ]
DecimalPlacesonly forNumber;Encrypted/ValidationRegexonly forString;Minimum/Maximummean length for strings and value for numbers/dates. - [ ] Every entity referenced by an FK must be in the payload or already exist in the target app.
- [ ] To expose a custom endpoint, add a
Securityrule withTypeID: 1andAction: "get". - [ ] Grant columns explicitly in each security rule's
Properties— anullgrants no non-PK columns. - [ ] For existing items, keep metadata identical to what is already in the app, or the import aborts. ```