OpenAPI Specifications
Understanding and using auto-generated OpenAPI documentation for dataset APIs
GoPie automatically generates OpenAPI 3.0 specifications for every dataset, providing machine-readable API documentation, client SDK generation, and interactive API exploration.
OpenAPI Generation Flow
Accessing OpenAPI Documentation
Available Endpoints
# Get OpenAPI specification (JSON)
GET /api/v1/datasets/{dataset_id}/openapi.json
# Get OpenAPI specification (YAML)
GET /api/v1/datasets/{dataset_id}/openapi.yaml
# Interactive Swagger UI
GET /api/v1/datasets/{dataset_id}/docs
# ReDoc documentation
GET /api/v1/datasets/{dataset_id}/redoc
# Download client SDK
GET /api/v1/datasets/{dataset_id}/sdk/{language}Example OpenAPI Specification
openapi: 3.0.3
info:
title: Customers Dataset API
description: |
Auto-generated REST API for the Customers dataset.
This API provides full CRUD operations, advanced querying,
aggregations, and bulk operations for managing customer data.
version: 1.0.0
contact:
name: GoPie Support
email: [email protected]
x-dataset-id: ds_customers_2024
x-generated-at: "2024-01-20T10:00:00Z"
servers:
- url: https://api.gopie.io/api/v1
description: Production server
- url: https://staging-api.gopie.io/api/v1
description: Staging server
tags:
- name: Records
description: CRUD operations on customer records
- name: Query
description: Advanced query operations
- name: Bulk
description: Bulk operations
- name: Export
description: Data export operations
paths:
/datasets/{datasetId}/data:
get:
tags: [Records]
summary: List customer records
description: Retrieve paginated customer records with filtering and sorting
operationId: listCustomers
parameters:
- $ref: '#/components/parameters/DatasetId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Fields'
- name: filter[status]
in: query
schema:
type: string
enum: [active, inactive, pending]
description: Filter by customer status
- name: filter[created_at][gte]
in: query
schema:
type: string
format: date-time
description: Filter by creation date (greater than or equal)
- name: search
in: query
schema:
type: string
description: Full-text search across name and email
responses:
'200':
description: List of customers
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerList'
examples:
success:
$ref: '#/components/examples/CustomerListExample'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/RateLimitExceeded'
x-code-samples:
- lang: 'cURL'
source: |
curl -X GET "https://api.gopie.io/api/v1/datasets/ds_customers/data?page=1&limit=20" \
-H "Authorization: Bearer YOUR_TOKEN"
- lang: 'JavaScript'
source: |
const response = await fetch('https://api.gopie.io/api/v1/datasets/ds_customers/data?page=1&limit=20', {
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
}
});
const customers = await response.json();
post:
tags: [Records]
summary: Create a new customer
operationId: createCustomer
parameters:
- $ref: '#/components/parameters/DatasetId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerCreate'
examples:
newCustomer:
$ref: '#/components/examples/CustomerCreateExample'
responses:
'201':
description: Customer created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
headers:
Location:
schema:
type: string
description: URL of the created resource
'400':
$ref: '#/components/responses/ValidationError'
'409':
$ref: '#/components/responses/Conflict'
/datasets/{datasetId}/data/{recordId}:
get:
tags: [Records]
summary: Get a customer by ID
operationId: getCustomer
parameters:
- $ref: '#/components/parameters/DatasetId'
- $ref: '#/components/parameters/RecordId'
- $ref: '#/components/parameters/Fields'
- $ref: '#/components/parameters/Include'
responses:
'200':
description: Customer details
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
'404':
$ref: '#/components/responses/NotFound'
put:
tags: [Records]
summary: Update a customer
operationId: updateCustomer
parameters:
- $ref: '#/components/parameters/DatasetId'
- $ref: '#/components/parameters/RecordId'
- $ref: '#/components/parameters/IfMatch'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerUpdate'
responses:
'200':
description: Customer updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
'409':
$ref: '#/components/responses/OptimisticLockError'
patch:
tags: [Records]
summary: Partially update a customer
operationId: patchCustomer
parameters:
- $ref: '#/components/parameters/DatasetId'
- $ref: '#/components/parameters/RecordId'
requestBody:
required: true
content:
application/json-patch+json:
schema:
$ref: '#/components/schemas/JsonPatch'
responses:
'200':
description: Customer patched successfully
delete:
tags: [Records]
summary: Delete a customer
operationId: deleteCustomer
parameters:
- $ref: '#/components/parameters/DatasetId'
- $ref: '#/components/parameters/RecordId'
- name: soft
in: query
schema:
type: boolean
default: true
description: Perform soft delete
responses:
'204':
description: Customer deleted successfully
'404':
$ref: '#/components/responses/NotFound'
/datasets/{datasetId}/data/query:
post:
tags: [Query]
summary: Execute custom SQL query
operationId: queryCustomers
parameters:
- $ref: '#/components/parameters/DatasetId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/QueryRequest'
responses:
'200':
description: Query results
content:
application/json:
schema:
$ref: '#/components/schemas/QueryResponse'
/datasets/{datasetId}/data/aggregate:
get:
tags: [Query]
summary: Perform aggregations
operationId: aggregateCustomers
parameters:
- $ref: '#/components/parameters/DatasetId'
- name: group_by
in: query
required: true
schema:
type: string
description: Fields to group by
- name: agg
in: query
required: true
schema:
type: string
description: Aggregation functions
responses:
'200':
description: Aggregation results
content:
application/json:
schema:
$ref: '#/components/schemas/AggregationResponse'
/datasets/{datasetId}/data/bulk:
post:
tags: [Bulk]
summary: Bulk operations
operationId: bulkOperations
parameters:
- $ref: '#/components/parameters/DatasetId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BulkRequest'
responses:
'200':
description: Bulk operation results
content:
application/json:
schema:
$ref: '#/components/schemas/BulkResponse'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: JWT token authentication
apiKey:
type: apiKey
in: header
name: X-API-Key
description: API key authentication
parameters:
DatasetId:
name: datasetId
in: path
required: true
schema:
type: string
pattern: '^ds_[a-z0-9_]+$'
description: Dataset identifier
example: ds_customers
RecordId:
name: recordId
in: path
required: true
schema:
type: string
description: Record identifier
Page:
name: page
in: query
schema:
type: integer
minimum: 1
default: 1
description: Page number
Limit:
name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 1000
default: 20
description: Records per page
Sort:
name: sort
in: query
schema:
type: string
description: Sort fields (prefix with - for DESC)
example: '-created_at,name'
Fields:
name: fields
in: query
schema:
type: string
description: Comma-separated fields to include
example: 'id,name,email'
Include:
name: include
in: query
schema:
type: string
description: Related resources to include
example: 'orders,addresses'
IfMatch:
name: If-Match
in: header
schema:
type: string
description: ETag for optimistic concurrency control
schemas:
Customer:
type: object
required: [id, name, email, status, created_at]
properties:
id:
type: integer
format: int64
readOnly: true
description: Unique identifier
name:
type: string
minLength: 1
maxLength: 255
description: Customer full name
email:
type: string
format: email
maxLength: 255
description: Email address
phone:
type: string
pattern: '^\+?[1-9]\d{1,14}$'
description: Phone number in E.164 format
address:
$ref: '#/components/schemas/Address'
status:
type: string
enum: [active, inactive, pending]
description: Account status
tags:
type: array
items:
type: string
description: Customer tags
metadata:
type: object
additionalProperties: true
description: Custom metadata
created_at:
type: string
format: date-time
readOnly: true
updated_at:
type: string
format: date-time
readOnly: true
_links:
type: object
readOnly: true
properties:
self:
type: string
format: uri
orders:
type: string
format: uri
CustomerCreate:
type: object
required: [name, email]
properties:
name:
type: string
minLength: 1
maxLength: 255
email:
type: string
format: email
phone:
type: string
address:
$ref: '#/components/schemas/Address'
status:
type: string
enum: [active, inactive, pending]
default: pending
tags:
type: array
items:
type: string
metadata:
type: object
CustomerUpdate:
allOf:
- $ref: '#/components/schemas/CustomerCreate'
- type: object
properties:
version:
type: integer
description: Version for optimistic locking
Address:
type: object
properties:
street:
type: string
city:
type: string
state:
type: string
maxLength: 2
zip:
type: string
pattern: '^\d{5}(-\d{4})?$'
country:
type: string
default: 'US'
CustomerList:
type: object
required: [data, pagination]
properties:
data:
type: array
items:
$ref: '#/components/schemas/Customer'
pagination:
$ref: '#/components/schemas/Pagination'
meta:
$ref: '#/components/schemas/ResponseMeta'
Pagination:
type: object
required: [page, limit, total, pages]
properties:
page:
type: integer
limit:
type: integer
total:
type: integer
pages:
type: integer
has_next:
type: boolean
has_prev:
type: boolean
next_cursor:
type: string
prev_cursor:
type: string
QueryRequest:
type: object
required: [sql]
properties:
sql:
type: string
description: SQL query (SELECT only)
parameters:
type: object
additionalProperties: true
options:
type: object
properties:
timeout:
type: integer
cache:
type: boolean
cache_ttl:
type: integer
QueryResponse:
type: object
properties:
data:
type: array
items:
type: object
meta:
type: object
properties:
row_count:
type: integer
execution_time_ms:
type: integer
schema:
type: array
items:
type: object
properties:
name:
type: string
type:
type: string
nullable:
type: boolean
BulkRequest:
type: object
required: [operations]
properties:
operations:
type: array
items:
type: object
required: [method]
properties:
method:
type: string
enum: [create, update, delete]
data:
type: object
filter:
type: object
ids:
type: array
items:
type: string
options:
type: object
properties:
atomic:
type: boolean
continue_on_error:
type: boolean
BulkResponse:
type: object
properties:
succeeded:
type: integer
failed:
type: integer
results:
type: array
items:
type: object
properties:
index:
type: integer
success:
type: boolean
id:
type: string
error:
type: object
Error:
type: object
required: [code, message]
properties:
code:
type: string
message:
type: string
details:
type: array
items:
type: object
properties:
field:
type: string
code:
type: string
message:
type: string
request_id:
type: string
documentation_url:
type: string
format: uri
ResponseMeta:
type: object
properties:
version:
type: string
request_id:
type: string
execution_time_ms:
type: integer
JsonPatch:
type: array
items:
type: object
required: [op, path]
properties:
op:
type: string
enum: [add, remove, replace, move, copy, test]
path:
type: string
value:
type: any
from:
type: string
AggregationResponse:
type: object
properties:
data:
type: array
items:
type: object
meta:
type: object
properties:
groups:
type: integer
aggregations:
type: object
additionalProperties: true
responses:
BadRequest:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Conflict:
description: Resource conflict
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
ValidationError:
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
code: VALIDATION_ERROR
message: Validation failed
details:
- field: email
code: invalid_format
message: Email format is invalid
RateLimitExceeded:
description: Rate limit exceeded
headers:
X-RateLimit-Limit:
schema:
type: integer
X-RateLimit-Remaining:
schema:
type: integer
X-RateLimit-Reset:
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
OptimisticLockError:
description: Optimistic lock error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
CustomerListExample:
value:
data:
- id: 1
name: John Doe
email: [email protected]
status: active
created_at: '2024-01-15T10:00:00Z'
pagination:
page: 1
limit: 20
total: 150
pages: 8
CustomerCreateExample:
value:
name: Jane Smith
email: [email protected]
phone: '+1234567890'
address:
street: 123 Main St
city: New York
state: NY
zip: '10001'
status: active
security:
- bearerAuth: []
- apiKey: []
x-tagGroups:
- name: Core Operations
tags:
- Records
- name: Advanced Features
tags:
- Query
- Bulk
- ExportSchema Generation Rules
Type Mapping
GoPie automatically maps database types to OpenAPI types:
| Database Type | OpenAPI Type | Format | Constraints |
|---|---|---|---|
INTEGER | integer | int32 or int64 | min/max from DB |
DECIMAL | number | double | precision/scale |
VARCHAR(n) | string | - | maxLength: n |
TEXT | string | - | No length limit |
BOOLEAN | boolean | - | - |
DATE | string | date | ISO 8601 |
TIMESTAMP | string | date-time | ISO 8601 |
JSON | object | - | additionalProperties |
UUID | string | uuid | pattern validation |
ENUM | string | - | enum values |
ARRAY | array | - | items type |
Constraint Detection
# Database constraint to OpenAPI schema
# NOT NULL → required field
# UNIQUE → x-unique: true
# CHECK → pattern/min/max
# DEFAULT → default value
# FOREIGN KEY → relationship links
properties:
email:
type: string
format: email
maxLength: 255
x-unique: true
x-database-type: VARCHAR(255)
x-constraints:
- type: unique
name: uk_customers_emailRelationship Handling
# One-to-Many relationship
Customer:
properties:
orders:
type: array
items:
$ref: '#/components/schemas/OrderSummary'
x-relationship:
type: one-to-many
target: orders
foreign_key: customer_id
# Many-to-Many relationship
Product:
properties:
categories:
type: array
items:
$ref: '#/components/schemas/Category'
x-relationship:
type: many-to-many
junction_table: product_categories
local_key: product_id
foreign_key: category_idCustomization
Schema Extensions
Add custom extensions to generated schemas:
{
"x-display-name": "Customer Management API",
"x-logo": {
"url": "https://example.com/logo.png",
"altText": "Company Logo"
},
"x-documentation": {
"external_docs": "https://docs.example.com",
"code_samples": true,
"playground": true
},
"x-security": {
"rate_limit": "1000/hour",
"require_https": true,
"cors_origins": ["https://app.example.com"]
}
}Custom Validation Rules
# Add custom validation via extensions
CustomerCreate:
properties:
email:
type: string
format: email
x-validation:
- rule: unique
message: Email already exists
- rule: domain
allowed: ["company.com", "partner.com"]
message: Must use company email
age:
type: integer
x-validation:
- rule: custom
function: validateAge
message: Must be 18 or olderClient SDK Generation
Supported Languages
# Generate JavaScript SDK
GET /api/v1/datasets/ds_customers/sdk/javascript
# Generate TypeScript SDK with types
GET /api/v1/datasets/ds_customers/sdk/typescriptGenerated SDK example:
// customers-sdk.ts
export interface Customer {
id: number;
name: string;
email: string;
status: 'active' | 'inactive' | 'pending';
created_at: string;
updated_at: string;
}
export class CustomersAPI {
constructor(private apiKey: string, private baseUrl = 'https://api.gopie.io') {}
async list(params?: {
page?: number;
limit?: number;
filter?: Record<string, any>;
sort?: string;
}): Promise<{ data: Customer[]; pagination: Pagination }> {
// Implementation
}
async get(id: string | number): Promise<Customer> {
// Implementation
}
async create(data: Omit<Customer, 'id' | 'created_at' | 'updated_at'>): Promise<Customer> {
// Implementation
}
async update(id: string | number, data: Partial<Customer>): Promise<Customer> {
// Implementation
}
async delete(id: string | number, soft = true): Promise<void> {
// Implementation
}
async query(sql: string, parameters?: Record<string, any>): Promise<QueryResult> {
// Implementation
}
}# Generate Python SDK
GET /api/v1/datasets/ds_customers/sdk/pythonGenerated SDK example:
# customers_sdk.py
from typing import List, Optional, Dict, Any
from dataclasses import dataclass
from datetime import datetime
import requests
@dataclass
class Customer:
id: int
name: str
email: str
status: str
created_at: datetime
updated_at: datetime
class CustomersAPI:
def __init__(self, api_key: str, base_url: str = "https://api.gopie.io"):
self.api_key = api_key
self.base_url = base_url
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
})
def list(self,
page: int = 1,
limit: int = 20,
filter: Optional[Dict[str, Any]] = None,
sort: Optional[str] = None) -> Dict[str, Any]:
"""List customers with pagination"""
params = {"page": page, "limit": limit}
if filter:
params.update({f"filter[{k}]": v for k, v in filter.items()})
if sort:
params["sort"] = sort
response = self.session.get(
f"{self.base_url}/api/v1/datasets/ds_customers/data",
params=params
)
response.raise_for_status()
return response.json()
def create(self, customer: Dict[str, Any]) -> Customer:
"""Create a new customer"""
response = self.session.post(
f"{self.base_url}/api/v1/datasets/ds_customers/data",
json=customer
)
response.raise_for_status()
return Customer(**response.json())# Generate Go SDK
GET /api/v1/datasets/ds_customers/sdk/goGenerated SDK example:
// customers/client.go
package customers
import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"
)
type Customer struct {
ID int64 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type Client struct {
apiKey string
baseURL string
httpClient *http.Client
}
func NewClient(apiKey string) *Client {
return &Client{
apiKey: apiKey,
baseURL: "https://api.gopie.io",
httpClient: &http.Client{
Timeout: 30 * time.Second,
},
}
}
func (c *Client) List(ctx context.Context, opts ListOptions) (*ListResponse, error) {
req, err := c.newRequest(ctx, "GET", "/api/v1/datasets/ds_customers/data", nil)
if err != nil {
return nil, err
}
// Add query parameters
q := req.URL.Query()
if opts.Page > 0 {
q.Set("page", fmt.Sprintf("%d", opts.Page))
}
if opts.Limit > 0 {
q.Set("limit", fmt.Sprintf("%d", opts.Limit))
}
req.URL.RawQuery = q.Encode()
var resp ListResponse
err = c.do(req, &resp)
return &resp, err
}Interactive Documentation
Swagger UI Features
Access interactive API documentation at /api/v1/datasets/{dataset_id}/docs
Features available in Swagger UI:
- Try it out: Execute API calls directly from the browser
- Authentication: Configure auth tokens
- Request builder: Visual request parameter builder
- Response viewer: Formatted response display
- Code samples: Copy-paste ready examples
- Model viewer: Explore data schemas
ReDoc Features
Access ReDoc documentation at /api/v1/datasets/{dataset_id}/redoc:
- Search: Full-text search across documentation
- Navigation: Three-panel navigation
- Code samples: Multiple language examples
- Download: Export as PDF or OpenAPI file
- Deep linking: Direct links to operations
Versioning
API Version Management
# Version in OpenAPI spec
info:
version: 1.2.0
x-api-versions:
- version: "1.2.0"
status: "current"
released: "2024-01-20"
- version: "1.1.0"
status: "deprecated"
released: "2023-10-15"
sunset: "2024-04-20"
- version: "1.0.0"
status: "sunset"
released: "2023-06-01"
sunset: "2023-12-31"Version-specific Documentation
# Get specific version
GET /api/v1/datasets/ds_customers/openapi.json?version=1.1.0
# Get version changelog
GET /api/v1/datasets/ds_customers/changelogSchema Validation
Request Validation
Generated APIs automatically validate requests against OpenAPI schemas:
// Invalid request
POST /api/v1/datasets/ds_customers/data
{
"name": "J", // Too short
"email": "invalid-email", // Invalid format
"status": "unknown" // Not in enum
}
// Validation error response
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "name",
"code": "minLength",
"message": "String is too short (1 < 2)"
},
{
"field": "email",
"code": "format",
"message": "Does not match format 'email'"
},
{
"field": "status",
"code": "enum",
"message": "Value must be one of: active, inactive, pending"
}
]
}
}Response Validation
Responses are validated before sending:
- Ensures data consistency
- Removes unexpected fields
- Applies field-level security
- Formats dates and numbers
Security Definitions
Authentication Schemes
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
JWT authentication token.
Format: Bearer <token>
Obtain token via /auth/login endpoint.
Tokens expire after 1 hour.
apiKey:
type: apiKey
in: header
name: X-API-Key
description: |
API key for service-to-service auth.
Generate keys in dashboard.
Keys don't expire but can be revoked.
oauth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.gopie.io/oauth/authorize
tokenUrl: https://auth.gopie.io/oauth/token
scopes:
read: Read access to data
write: Create and update data
delete: Delete data
admin: Full administrative accessSecurity Requirements
# Global security (applies to all endpoints)
security:
- bearerAuth: []
- apiKey: []
# Operation-specific security
paths:
/datasets/{datasetId}/data:
delete:
security:
- bearerAuth: []
oauth2: [delete, admin]
description: Requires delete scopeExtensions and Plugins
Custom Extensions
# Dataset-specific extensions
x-dataset-config:
soft_delete: true
audit_trail: true
row_level_security: true
encryption_at_rest: true
# Field-level extensions
properties:
ssn:
type: string
x-pii: true
x-encryption: required
x-access-control:
read: ["admin", "owner"]
write: ["admin"]Code Generation Plugins
# Configure code generation
x-generator-config:
javascript:
package_name: "@company/customers-sdk"
use_promises: true
include_typescript: true
python:
package_name: "customers_sdk"
use_async: true
go:
package_name: "github.com/company/customers"
use_generics: trueBest Practices
- Keep specs up-to-date: Regenerate after schema changes
- Use semantic versioning: Major.Minor.Patch
- Document deprecations: Provide migration guides
- Include examples: Real-world request/response examples
- Add descriptions: Explain fields and operations
- Test with validators: Use OpenAPI validators
- Monitor usage: Track deprecated endpoint usage
Troubleshooting
Common Issues
-
Schema Generation Fails
# Check dataset schema GET /api/v1/datasets/ds_customers/schema # Validate schema manually POST /api/v1/datasets/ds_customers/validate-schema -
SDK Generation Errors
# Get generation logs GET /api/v1/datasets/ds_customers/sdk/logs # Validate OpenAPI spec POST /api/v1/validate/openapi -
Version Conflicts
# Check available versions GET /api/v1/datasets/ds_customers/versions # Get version compatibility GET /api/v1/datasets/ds_customers/compatibility
Next Steps
- Explore Generated Endpoints in detail
- Learn about API Authentication
- Understand Pagination Patterns
- Review API Best Practices