Overview
This guide provides examples of implementing REST API endpoints in OutSystems for tracking publish activity and application metrics. Includes database queries, response structures, and security considerations.
Setup
- Create a new REST API in Service Studio
- Name it:
ActivityAPI - Set version to:
v1 - Configure CORS if needed (see below)
Endpoint 1: GetPublishActivity
Method: GET
Path: /publish-activity
Input Parameters
DaysBack(Integer, Optional, Default: 30)Application(Text, Optional, Default: "")
Server Action Logic
SELECT
e.Name AS ApplicationName,
CONVERT(VARCHAR, mv.VERSION_ID) AS VersionID,
mv.VERSION AS Version,
mv.UPLOADED_DATE AS PublishDate,
mv.UPLOADED_BY AS PublishedBy,
e.IS_ACTIVE AS IsActive,
ISNULL(ss.NAME, '') AS Solution
FROM
ossys_Module_Version mv
INNER JOIN
ossys_Espace e ON mv.ESPACE_ID = e.ID
LEFT JOIN
ossys_Solution_Espace se ON e.ID = se.ESPACE_ID
LEFT JOIN
ossys_Solution ss ON se.SOLUTION_ID = ss.ID
WHERE
mv.UPLOADED_DATE >= DATEADD(day, -@DaysBack, GETDATE())
AND (@Application = '' OR e.Name = @Application)
ORDER BY
mv.UPLOADED_DATE DESC
Output Structure
Create a Structure called PublishActivityRecord:
- ApplicationName (Text)
- VersionID (Text)
- Version (Text)
- PublishDate (DateTime)
- PublishedBy (Text)
- IsActive (Boolean)
- Solution (Text)
Create a Structure called PublishActivityResponse:
- data (List of PublishActivityRecord)
- totalRecords (Integer)
- dateRange (DateRangeInfo)
Create a Structure called DateRangeInfo:
- start (DateTime)
- end (DateTime)
Response Mapping
In the REST API method:
- Call the Server Action with input parameters
- Assign the result to response.data
- Calculate response.totalRecords = Length(data)
- Set response.dateRange.start and response.dateRange.end
Endpoint 2: GetApplicationList
Method: GET
Path: /application-list
Input Parameters
None
Server Action Logic
SELECT
CONVERT(VARCHAR, e.ID) AS ID,
e.Name AS ApplicationName,
e.IS_ACTIVE AS IsActive,
COUNT(mv.VERSION_ID) AS TotalPublishes,
MAX(mv.UPLOADED_DATE) AS LastPublish,
MIN(mv.UPLOADED_DATE) AS FirstPublish
FROM
ossys_Espace e
LEFT JOIN
ossys_Module_Version mv ON e.ID = mv.ESPACE_ID
GROUP BY
e.ID, e.Name, e.IS_ACTIVE
ORDER BY
e.Name
Output Structure
Create a Structure called ApplicationInfo:
- ID (Text)
- ApplicationName (Text)
- IsActive (Boolean)
- TotalPublishes (Integer)
- LastPublish (DateTime)
- FirstPublish (DateTime)
Create a Structure called ApplicationListResponse:
- data (List of ApplicationInfo)
- totalApplications (Integer)
Response Mapping
In the REST API method:
- Call the Server Action
- Assign the result to response.data
- Calculate response.totalApplications = Length(data)
Endpoint 3: GetDailySummary
Method: GET
Path: /daily-summary
Input Parameters
DaysBack(Integer, Optional, Default: 30)
Server Action Logic
SELECT
CONVERT(VARCHAR, CAST(mv.UPLOADED_DATE AS DATE), 23) AS PublishDate,
COUNT(*) AS PublishCount,
COUNT(DISTINCT mv.ESPACE_ID) AS UniqueApplications,
COUNT(DISTINCT mv.UPLOADED_BY) AS UniqueDevelopers
FROM
ossys_Module_Version mv
WHERE
mv.UPLOADED_DATE >= DATEADD(day, -@DaysBack, GETDATE())
GROUP BY
CAST(mv.UPLOADED_DATE AS DATE)
ORDER BY
CAST(mv.UPLOADED_DATE AS DATE) ASC
Output Structure
Create a Structure called DailySummaryRecord:
- PublishDate (Text) — Format: YYYY-MM-DD
- PublishCount (Integer)
- UniqueApplications (Integer)
- UniqueDevelopers (Integer)
Create a Structure called DailySummaryResponse:
- data (List of DailySummaryRecord)
Response Mapping
In the REST API method:
- Call the Server Action with DaysBack parameter
- Assign the result to response.data
CORS Configuration
If your dashboard is hosted separately from your OutSystems server, add these response headers to each REST method.
OnRequest Callback
Create a Server Action called SetCORSHeaders and add to the OnRequest callback:
SetHTTPHeader(
Name: "Access-Control-Allow-Origin",
Value: "*" // Or specify your domain: "https://your-dashboard.com"
)
SetHTTPHeader(
Name: "Access-Control-Allow-Methods",
Value: "GET, OPTIONS"
)
SetHTTPHeader(
Name: "Access-Control-Allow-Headers",
Value: "Content-Type, Authorization"
)
Handle OPTIONS Requests
Create a REST method for OPTIONS:
- Method: OPTIONS
- Path:
/* - Returns: Empty response with 204 status code
Testing Your Endpoints
Test in OutSystems
- Publish your REST API
- Click “Open Documentation” on the REST API
- Try the endpoints in the Swagger interface
Test in Browser
// Open browser console and test
fetch('https://your-server/YourApp/rest/ActivityAPI/v1/publish-activity?daysBack=7')
.then(res => res.json())
.then(data => console.log(data));
Test with PowerShell
# Test the API
$response = Invoke-RestMethod -Uri "https://your-server/YourApp/rest/ActivityAPI/v1/publish-activity?daysBack=7"
$response | ConvertTo-Json -Depth 5
Example Full REST API Structure
ActivityAPI (REST API)
├── v1
│ ├── GetPublishActivity (GET /publish-activity)
│ │ ├── Input: DaysBack, Application
│ │ └── Output: PublishActivityResponse
│ ├── GetApplicationList (GET /application-list)
│ │ ├── Input: None
│ │ └── Output: ApplicationListResponse
│ └── GetDailySummary (GET /daily-summary)
│ ├── Input: DaysBack
│ └── Output: DailySummaryResponse
└── OnRequest: SetCORSHeaders
Performance Optimization Tips
Cache Results
For frequently accessed data, consider using OutSystems caching:
// In Server Action
If CachedData Is Valid Then
Return CachedData
Else
FetchedData = QueryData()
CacheData(FetchedData, Duration: #24 Hours#)
Return FetchedData
Limit Results
Add pagination parameters if datasets are large.
Background Processing
For complex aggregations, consider:
- Timer to pre-calculate daily summaries
- Store results in custom entities
- REST API reads from pre-calculated data
Security Considerations
Authentication
Add authentication to your REST API:
- Use OutSystems built-in authentication
- Require API keys
- Implement token-based auth
Authorization
Check user permissions:
If Not CheckActivityAPIPermission(GetUserId()) Then
Throw Unauthorized Exception
Rate Limiting
Implement rate limiting to prevent abuse.
Input Validation
Always validate input parameters:
If DaysBack < 1 Or DaysBack > 365 Then
Throw Invalid Parameter Exception
Sensitive Data
Avoid exposing sensitive information:
- Filter out internal applications
- Mask or exclude personal data
- Log API access for auditing
Deployment Checklist
- Create REST API in Service Studio
- Implement all three endpoints
- Add CORS headers if needed
- Test each endpoint with sample data
- Verify JSON response format
- Check performance with realistic data volumes
- Add authentication/authorization
- Deploy to development environment
- Update dashboard with API endpoint URL
- Test end-to-end integration
- Deploy to production