Public Endpoints for Restricted (Closed) Deployments

When deploying Countly in a restricted environment, you may want to keep your dashboard and internal APIs private, exposing only the endpoints required for external communication. This guide outlines which endpoints must be publicly accessible, which service handles each endpoint, and how to configure your network allowlists accordingly.

Overview

Countly consists of two main services:

  • API: Handles event ingestion, SDK configuration, and widget data.

  • Frontend: Serves static assets, Web SDK, widgets UI, images, and tracking pixels.

Recommendation: Expose only the endpoints required for the features you use. Keep all other paths private.

Public Endpoints by Feature

Note: Unless otherwise specified, most endpoints support both GET and POST methods. Allow both methods in your firewall or proxy configuration for maximum compatibility.

1. Event Collection (SDK Ingestion)

Service: API
Required if: Applications or websites send analytics data.

Method Path Description
GET/POST /i Standard event/session ingestion
GET/POST /i/bulk Bulk ingestion
GET/POST /i/campaign/click/* Attribution campaign click tracking

2. Remote Config & A/B Testing

Service: API
Required if: SDKs fetch configuration or experiment variants.

Method Path Description
GET/POST /o/sdk Remote config & A/B tests

3. Heatmaps

Service:

  • Data: API
  • Rendering assets: Frontend
Method Path Description
GET/POST /o/actions Heatmap data (API)
GET /views/heatmap.js Heatmap JS (FE)
GET /views/javascripts/simpleheat.js Heatmap JS (FE)
GET /views/stylesheets/heatmap.css Heatmap CSS

4. Surveys, NPS, and Feedback Widgets

Widget Data: API
UI & Static Assets: Frontend

Method Path Description
GET/POST /o/feedback/multiple-widgets-by-id Widget data (API)
GET/POST /o/feedback/widget Widget data (API)
GET/POST /o/surveys/survey/widget Survey data (API)
GET/POST /o/surveys/nps/widget NPS data (API)
GET /feedback, /feedback/* Widget UI (FE)
GET /surveys/* Survey UI (FE)
GET /star-rating/* Star rating UI (FE)
GET /javascripts/dom/jquery/* JS assets (FE)
GET /stylesheets/font-awesome/css/* Fonts/icons (FE)
GET /stylesheets/font-awesome/fonts/* Fonts/icons (FE)
GET /stylesheets/ionicons/* Fonts/icons (FE)
GET /fonts/* Fonts (FE)

5. In-App Messages / Content Blocks

Service: Frontend
Required if: Using content blocks or in-app messaging delivered from the server.

Method Path Description
GET /_external/content/ Content block delivery
GET /_external/content/asset/ Content assets (images)

6. Web SDK Hosting

Service: Frontend
Required if: The Web SDK is loaded from your Countly server.

Method Path Description
GET /sdk/web/countly.min.js Web SDK file

7. Tracking Pixel

Service: Frontend
Required if: Using email or lightweight tracking.

Method Path Description
GET /pixel.png Tracking pixel

8. Attribution Short Links

Service: Frontend
Required if: Using campaign redirects.

Method Path Description
GET /at/* Attribution links
GET /campaign/* Campaign redirects

9. Email Report Assets

Service: Frontend
Required if: Email reports include externally hosted images.

Method Path Description
GET /images/dashboard/countly_logo.svg Logo asset
GET /images/dashboard/logo.png Logo asset
GET /images/pre-login/countly-logo-dark.svg Logo asset
GET /images/pre-login/countly-logo.svg Logo asset
GET /appimages/*.png App images
GET /dashboards/images/screenshots/screenshot_*.png Dashboard screenshots

Example: NGINX Allowlist

Route requests to the correct service and block everything else.

upstream api {
    server countly-api:3001;
}
upstream frontend {
    server countly-frontend:3000;
}
server {
    listen 443 ssl;
    server_name analytics.example.com;

    # Default: deny everything
    location / { return 404; }

    # --- API endpoints ---
    location = /i { proxy_pass http://api; }
    location = /i/bulk { proxy_pass http://api; }
    location ~ ^/i/campaign/click/ { proxy_pass http://api; }
    location = /o/sdk { proxy_pass http://api; }
    location = /o/actions { proxy_pass http://api; }
    location = /o/feedback/multiple-widgets-by-id { proxy_pass http://api; }
    location = /o/feedback/widget { proxy_pass http://api; }
    location = /o/surveys/survey/widget { proxy_pass http://api; }
    location = /o/surveys/nps/widget { proxy_pass http://api; }

    # --- Frontend endpoints ---
    location = /pixel.png { proxy_pass http://frontend; }
    location = /sdk/web/countly.min.js { proxy_pass http://frontend; }
    location ~ ^/views/ { proxy_pass http://frontend; }
    location ~ ^/feedback { proxy_pass http://frontend; }
    location ~ ^/surveys/ { proxy_pass http://frontend; }
    location ~ ^/star-rating/ { proxy_pass http://frontend; }
    location ~ ^/stylesheets/font-awesome/ { proxy_pass http://frontend; }
    location ~ ^/stylesheets/ionicons/ { proxy_pass http://frontend; }
    location ~ ^/fonts/ { proxy_pass http://frontend; }
    location ~ ^/_external/content/ { proxy_pass http://frontend; }
    location ~ ^/at/ { proxy_pass http://frontend; }
    location ~ ^/campaign/ { proxy_pass http://frontend; }
    location ~ ^/images/ { proxy_pass http://frontend; }
    location ~ ^/appimages/ { proxy_pass http://frontend; }
    location ~ ^/dashboards/images/screenshots/ { proxy_pass http://frontend; }
}

Kubernetes Ingress (Concept)

Expose only required paths and route them to the appropriate service:

Path Service
/i*, /o* API
/views*, /feedback*, /surveys*, /images*, /sdk*, /_external/content* Frontend

If you need further assistance configuring your deployment, please contact Countly Support.

Future Changes: In future versions, most public endpoints may be consolidated under a common prefix (e.g., /_external) to simplify the allowlist configuration.

Was this page helpful?
Reach out to us for any other questions.
Helpful?

Looking for more Help?