Skip to main content
POST
/
{collection}
Create Document
curl --request POST \
  --url https://api.example.com/{collection} \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "field_name": "<any>"
}
'
{
  "_id": "<string>",
  "created_at": "<string>",
  "updated_at": "<string>",
  "created_by": "<string>",
  "...": "<any>"
}

Overview

Creates a new document in the specified collection. The endpoint automatically:
  • Validates the document against the collection schema
  • Populates created_at, updated_at, created_by fields
  • Applies tenant isolation if configured
  • Executes pre/post-create hooks
  • Enforces RBAC permissions
  • Logs the operation to audit trail

Request

Path Parameters

collection
string
required
The name of the collection to create the document in

Headers

Authorization
string
required
Bearer token for authentication

Body

The request body should contain a JSON object representing the document to create. All fields will be validated against the collection’s schema.
field_name
any
Custom fields as defined in your collection schema. The system automatically adds:
  • created_at (timestamp)
  • updated_at (timestamp)
  • created_by (user ID from auth context)
  • Tenant/owner fields if configured in the collection’s access settings

Response

_id
string
The unique identifier of the newly created document
created_at
string
ISO 8601 timestamp when the document was created
updated_at
string
ISO 8601 timestamp when the document was last updated
created_by
string
User ID of the user who created the document
...
any
All other fields from your request body, filtered by field-level permissions

Examples

Basic Create

curl -X POST https://api.example.com/users \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "[email protected]",
    "role": "member"
  }'

Response

{
  "_id": "507f1f77bcf86cd799439011",
  "name": "John Doe",
  "email": "[email protected]",
  "role": "member",
  "created_at": "2024-03-15T10:30:00Z",
  "updated_at": "2024-03-15T10:30:00Z",
  "created_by": "user_123",
  "company_id": "company_456"
}

Implementation Details

MongoDB Query Pattern

The handler uses MongoDB’s insertOne operation:
result, err := collection.InsertOne(ctx, doc)
if err != nil {
    return err
}
id := result.InsertedID

Workflow

  1. Extract collection name from URL path (handlers_crud.go:67)
  2. Authenticate request and extract auth context (handlers_crud.go:74)
  3. Validate collection exists in schema config (handlers_crud.go:81)
  4. Check RBAC permissions for create action (handlers_crud.go:90)
  5. Parse JSON body and validate structure (handlers_crud.go:99)
  6. Auto-populate fields:
    • created_by, created_at, updated_at (handlers_crud.go:108-111)
    • Tenant field (e.g., company_id) from auth context (handlers_crud.go:114)
    • Owner field if configured (handlers_crud.go:117)
  7. Validate against schema using validator (handlers_crud.go:122)
  8. Execute pre-create hooks if configured (handlers_crud.go:134)
  9. Insert into MongoDB using store.Create (handlers_crud.go:155)
  10. Execute post-create hooks (best-effort) (handlers_crud.go:168)
  11. Log audit event with success/failure (handlers_crud.go:183)
  12. Apply field policy to filter response fields (handlers_crud.go:186)
  13. Return 201 Created with document (handlers_crud.go:189)

Automatic Field Population

now := time.Now().UTC()
doc["created_by"] = authCtx.UserID
doc["created_at"] = now
doc["updated_at"] = now

// Set tenant/company_id from auth if configured
if collConfig.Access.TenantField != "" {
    doc[collConfig.Access.TenantField] = authCtx.TenantID
}
if collConfig.Access.OwnerField != "" {
    doc[collConfig.Access.OwnerField] = authCtx.UserID
}

Error Responses

400 Bad Request

Returned when:
  • Collection name is missing
  • Invalid JSON body
  • Schema validation fails
  • Pre-create hook fails
{
  "error": "Validation failed",
  "code": "schema_validation",
  "details": {
    "validation_errors": [
      {
        "field": "email",
        "code": "invalid_format",
        "message": "Invalid email format"
      }
    ]
  }
}

401 Unauthorized

{
  "error": "Authentication required"
}

403 Forbidden

Returned when user doesn’t have create permission:
{
  "error": "You don't have permission to perform this action",
  "code": "forbidden",
  "details": {
    "action": "create",
    "collection": "users"
  }
}

404 Not Found

Returned when collection doesn’t exist in schema:
{
  "error": "Collection not found",
  "code": "collection_not_found",
  "details": {
    "collection": "invalid_collection"
  }
}

500 Internal Server Error

{
  "error": "Failed to create document",
  "code": "internal_error",
  "details": {
    "error": "database connection failed"
  }
}

Hooks

You can intercept the create operation using hooks:

Pre-Create Hook

Executed before the document is inserted. Can modify the document or reject the operation:
function preCreate(event) {
  // event.after contains the document to be created
  // Modify or validate the document
  event.after.slug = event.after.name.toLowerCase().replace(/\s+/g, '-');
  return event;
}

Post-Create Hook

Executed after successful creation (best-effort, won’t fail the request):
function postCreate(event) {
  // event.after contains the created document with _id
  // Trigger side effects like notifications
  sendWelcomeEmail(event.after.email);
}

Build docs developers (and LLMs) love