Skip to main content

Overview

Every Gainable app includes automatically generated API endpoints. These APIs power your app’s functionality and can be used by external integrations.
You don’t need to know about APIs to use Gainable. This reference is for users who want to understand how their apps work internally or integrate with external systems.

API structure

For each data model you create, Gainable generates RESTful endpoints:
EndpointMethodDescription
/api/{model}GETList all items
/api/{model}POSTCreate new item
/api/{model}/:idGETGet single item
/api/{model}/:idPUTUpdate item
/api/{model}/:idDELETEDelete item

Example

If you create a Deal model, you get:
EndpointMethodDescription
/api/dealGETList all deals
/api/dealPOSTCreate new deal
/api/deal/:idGETGet specific deal
/api/deal/:idPUTUpdate deal
/api/deal/:idDELETEDelete deal

Response format

All API responses follow this structure:

Success response

{
  "success": true,
  "data": {
    "_id": "507f1f77bcf86cd799439011",
    "name": "Enterprise License",
    "amount": 50000,
    "status": "won",
    "createdAt": "2024-01-15T10:30:00.000Z",
    "updatedAt": "2024-01-15T10:30:00.000Z"
  }
}

List response

{
  "success": true,
  "data": [
    { "_id": "...", "name": "Deal 1", ... },
    { "_id": "...", "name": "Deal 2", ... }
  ]
}

Error response

{
  "success": false,
  "error": "Deal not found"
}

Common operations

Create an item

POST /api/deal
Content-Type: application/json

{
  "name": "Enterprise License",
  "amount": 50000,
  "status": "new"
}

Update an item

PUT /api/deal/507f1f77bcf86cd799439011
Content-Type: application/json

{
  "status": "won"
}

Delete an item

DELETE /api/deal/507f1f77bcf86cd799439011

Filtering

Most list endpoints support query parameters for filtering:
# Filter by status
GET /api/deal?status=won

# Filter by multiple fields
GET /api/deal?status=won&amount[$gte]=10000

# Sort results
GET /api/deal?sort=-createdAt

# Limit results
GET /api/deal?limit=10

Real-time events

When data changes, the server broadcasts events via WebSocket:
EventPayloadWhen
{model}:createdNew itemItem is created
{model}:updatedUpdated itemItem is modified
{model}:deletedDeleted item IDItem is deleted

Example events

// Listen for new deals
socket.on('deal:created', (deal) => {
  console.log('New deal:', deal);
});

// Listen for updates
socket.on('deal:updated', (deal) => {
  console.log('Deal updated:', deal);
});

// Listen for deletions
socket.on('deal:deleted', (data) => {
  console.log('Deal deleted:', data._id);
});

Authentication

API requests require authentication. Your app handles this automatically through session cookies when accessed through the browser. For external integrations, contact support for API key access.

Rate limits

APIs have reasonable rate limits to ensure stability:
  • Standard: 100 requests per minute
  • Bulk operations: 10 requests per minute
If you hit a rate limit, you’ll receive a 429 response.

Data types

Automatic fields

Every item includes:
FieldTypeDescription
_idObjectIdUnique identifier
createdAtDateCreation timestamp
updatedAtDateLast update timestamp

Reference fields

When models reference each other, the API returns IDs:
{
  "_id": "507f1f77bcf86cd799439011",
  "title": "Task 1",
  "project": "507f1f77bcf86cd799439012"
}
Use the project ID to fetch the related project.

Best practices

The app’s UI is the easiest way to interact with your data. Use APIs only when you need external integration.
Check for success: false responses and handle them appropriately.
Instead of polling, listen for WebSocket events to get instant updates.

Learn more