Schemas API
The Schemas API provides access to your project’s schema definitions. This is primarily used for code generation tools like UniformGen.
Overview
The Schemas API returns:
- Data Models - Custom content type definitions
- Block Types - Reusable content block schemas
- Customer Details - Customer profile field definitions
Authentication
The Schemas API requires a secret API key (sk_* prefix) for authentication. This is different from public API keys used for other operations.
curl -X POST https://api.foir.io/graphql/public \
-H "Content-Type: application/json" \
-H "x-api-key: sk_live_your_secret_key" \
-d '{"query": "{ projectSchemas { dataModels { handle name } } }"}'Queries
projectSchemas
Get all schemas for code generation.
query GetProjectSchemas {
projectSchemas {
dataModels {
id
handle
name
pluralName
description
fields {
id
key
type
label
required
isTranslatable
helpText
placeholder
defaultValue
options
validation {
type
value
message
}
}
}
blockTypes {
id
key
name
description
category
schema
}
customerDetailsSchema {
id
fields {
id
key
type
label
required
isTranslatable
}
}
}
}Required scope: schemas:read
Response Types
ProjectSchemas
type ProjectSchemas {
dataModels: [ProjectDataModelSchema!]!
blockTypes: [BlockTypeSchema!]!
customerDetailsSchema: CustomerDetailsSchema
}ProjectDataModelSchema
type ProjectDataModelSchema {
id: ID!
handle: String! # Unique identifier (e.g., "blog-post")
name: String! # Display name (e.g., "Blog Post")
pluralName: String! # Plural form (e.g., "Blog Posts")
description: String
fields: [SchemaFieldDefinition!]!
}SchemaFieldDefinition
type SchemaFieldDefinition {
id: ID!
key: String! # Field key (e.g., "title", "publishDate")
type: String! # Field type
label: String! # Display label
required: Boolean
isTranslatable: Boolean
helpText: String
placeholder: String
defaultValue: JSON
options: JSON # Type-specific options
validation: [ValidationRule!]
}ValidationRule
type ValidationRule {
type: String! # Rule type (min, max, pattern, etc.)
value: JSON # Rule value
message: String # Custom error message
}BlockTypeSchema
type BlockTypeSchema {
id: ID!
key: String! # Unique key (e.g., "hero-banner")
name: String! # Display name
description: String
category: String # Block category
schema: JSON! # JSON Schema definition
}Field Types
Common field types returned in SchemaFieldDefinition.type:
| Type | Description | Options |
|---|---|---|
text | Single-line text | maxLength, pattern |
richtext | Rich text editor | allowedBlocks |
number | Numeric value | min, max, decimals |
boolean | True/false | - |
date | Date picker | minDate, maxDate |
datetime | Date and time | minDate, maxDate |
select | Dropdown selection | options, multiple |
image | Image upload | maxSize, allowedTypes |
video | Video upload | maxSize, allowedTypes |
file | File upload | maxSize, allowedTypes |
link | URL with text | - |
json | Raw JSON | schema |
entity-reference | Entity relation | modelKey, multiple |
Example Response
{
"data": {
"projectSchemas": {
"dataModels": [
{
"id": "dm_abc123",
"handle": "blog-post",
"name": "Blog Post",
"pluralName": "Blog Posts",
"description": "Blog articles with author and categories",
"fields": [
{
"id": "fld_1",
"key": "title",
"type": "text",
"label": "Title",
"required": true,
"isTranslatable": true,
"validation": [
{
"type": "maxLength",
"value": 200,
"message": "Title must be under 200 characters"
}
]
},
{
"id": "fld_2",
"key": "content",
"type": "richtext",
"label": "Content",
"required": true,
"isTranslatable": true,
"options": {
"allowedBlocks": ["paragraph", "heading", "image", "quote"]
}
},
{
"id": "fld_3",
"key": "author",
"type": "entity-reference",
"label": "Author",
"required": true,
"options": {
"modelKey": "author",
"multiple": false
}
},
{
"id": "fld_4",
"key": "publishDate",
"type": "datetime",
"label": "Publish Date",
"required": false
}
]
}
],
"blockTypes": [
{
"id": "bt_xyz789",
"key": "hero-banner",
"name": "Hero Banner",
"description": "Full-width banner with image and CTA",
"category": "marketing",
"schema": {
"type": "object",
"properties": {
"heading": { "type": "string" },
"subheading": { "type": "string" },
"image": { "$ref": "#/definitions/image" },
"ctaText": { "type": "string" },
"ctaUrl": { "type": "string", "format": "uri" }
},
"required": ["heading", "image"]
}
}
],
"customerDetailsSchema": {
"id": "cds_001",
"fields": [
{
"id": "cdf_1",
"key": "firstName",
"type": "text",
"label": "First Name",
"required": true
},
{
"id": "cdf_2",
"key": "lastName",
"type": "text",
"label": "Last Name",
"required": true
},
{
"id": "cdf_3",
"key": "phone",
"type": "text",
"label": "Phone Number",
"required": false
}
]
}
}
}
}Use with UniformGen
The Schemas API is designed for use with UniformGen, which generates TypeScript types from your schemas:
# uniformgen.config.ts
export default {
apiEndpoint: 'https://api.foir.io/graphql/public',
apiKey: process.env.FOIR_SECRET_KEY,
output: './src/generated/foir-types.ts',
};npx uniformgenThis generates typed interfaces matching your schema definitions:
// Generated types
export interface BlogPost {
title: string;
content: RichTextContent;
author: EntityReference<Author>;
publishDate?: string;
}
export interface HeroBanner {
heading: string;
subheading?: string;
image: ImageField;
ctaText?: string;
ctaUrl?: string;
}Security Considerations
-
Never expose secret keys client-side - The Schemas API requires secret keys (
sk_*), which should only be used server-side or in build processes. -
Use in build pipelines - Typically used during CI/CD for code generation, not at runtime.
-
Cache responses - Schema definitions rarely change; cache responses to reduce API calls.
// Example: Cache schemas during build
import { writeFileSync } from 'fs';
async function generateTypes() {
const schemas = await fetchSchemas();
// Cache the response
writeFileSync('.cache/schemas.json', JSON.stringify(schemas));
// Generate types
generateTypescriptTypes(schemas);
}