Skip to main content
The network module is only available on website applications. Narrow the type with app.isWebsite() first:
const app = await api.applications.fetch("abc123def456abc123def456");

if (!app.isWebsite()) {
    throw new Error("This application is not a website");
}

app.network; // NetworkModule

Custom domain

app.network.setCustomDomain(domain) sets or removes the custom domain bound to the website.
await app.network.setCustomDomain("yoursite.com");

// Pass "@" to remove the configured custom domain
await app.network.setCustomDomain("@");
Custom domains require a Senior plan or higher. There is a daily per-user limit on how many times you can change a custom domain.
Attaching a custom domain beyond your plan’s load balancer limit (see Account-wide domains and load balancers below) fails with LOAD_BALANCER_LIMIT_REACHED (403).

DNS records

After attaching a custom domain you need to configure DNS at your registrar. app.network.dns() returns an array of DNS records to create.
const records = await app.network.dns();

for (const record of records) {
    console.log(`${record.type.toUpperCase()} ${record.name}${record.value} (${record.status})`);
}
Each record is { type, name, value, status }:
  • type is "txt" or "cname". TXT records cover domain ownership and SSL validation; the CNAME record carries traffic and always points value at cname.squareweb.app.
  • status reflects the current validation state, e.g. "pending", "pending_validation", or "active".

Analytics

app.network.analytics({ start, end }) returns aggregated edge analytics. start and end accept either ISO 8601 strings or Date objects. Maximum retention window is 7 days.
const since = new Date(Date.now() - 24 * 60 * 60 * 1000);

const analytics = await app.network.analytics({
    start: since,
    end: new Date(),
});

if ("visits" in analytics) {
    console.log(analytics.visits.length, "time buckets");
    console.log("Top countries:", analytics.countries.slice(0, 5));
    console.log("Top paths:",     analytics.paths.slice(0, 5));
}
For empty windows (e.g. before the app was created) the API returns {}. Guard with "visits" in analytics before reading.

Drill-down filters

Beyond start/end, analytics() accepts optional filters. Each filter narrows every breakdown in the response at once, not just one of them:
FilterNotes
country2-letter country code, e.g. "BR"
ipExact IP match
pathPrefix match, e.g. "/api"
statusHTTP status code, e.g. "404"
osOperating system
browserBrowser name
protocolRequest protocol
refererUse "Direct" for requests with no referer
providerNetwork provider, e.g. "GOOGLE (15169)" (ASN) or "SQUARE-CLOUD-PLATFORM"
contentTypeUse "Unknown" for unclassified content types
botUse "Unverified" for normal (non-bot) traffic
const analytics = await app.network.analytics({
    start: since,
    end: new Date(),
    country: "BR",
    status: "404",
    bot: "Unverified",
});

Breakdowns

Alongside the existing time-series and top-N breakdowns, the response includes four breakdowns computed over the whole window (no time series): ips (IPs originating from Square Cloud’s own network are masked), status_codes, bots, and content_types. Each entry has the shape { type, visits, requests, bytes }.
if ("ips" in analytics) {
    console.log("Top IPs:",           analytics.ips.slice(0, 5));
    console.log("Status codes:",      analytics.status_codes);
    console.log("Bot traffic:",       analytics.bots);
    console.log("Content types:",     analytics.content_types);
}

Error tracking

app.network.errors({ start, end, include4xx? }) returns the edge error breakdown. By default only 5xx errors are included.
const errors = await app.network.errors({
    start: since,
    end: new Date(),
    include4xx: true, // include 4xx alongside 5xx
});

if ("summary" in errors) {
    console.log(`Total: ${errors.summary.total}`);
    console.log("By class:",          errors.summary.by_class);
    console.log("Top failing paths:", errors.top_paths.slice(0, 3));
}

Per-request logs

app.network.logs({ start, end }) returns the per-request edge logs.
const logs = await app.network.logs({ start: since, end: new Date() });

for (const log of logs.slice(0, 5)) {
    console.log(
        log.timestamp,
        log.request.method, log.request.path,
        "→",
        log.response.status,
        `(${log.client.country ?? "??"})`,
    );
}
Per-request logs require a Pro plan or higher.

Latency percentiles

app.network.performance({ start, end }) returns p50 / p95 / p99 latencies for the edge and origin layers.
const perf = await app.network.performance({ start: since, end: new Date() });

if ("summary" in perf) {
    const { p50, p95, p99 } = perf.summary.edge;
    console.log(`Edge p50/p95/p99: ${p50}/${p95}/${p99}ms`);
    console.log("Slowest paths:", perf.slowest_paths.slice(0, 3));
}
Performance metrics require a Pro plan or higher.

Purging the edge cache

app.network.purgeCache() invalidates the entire edge cache for the application’s domains.
await app.network.purgeCache();

Account-wide domains and load balancers

domains() and loadBalancers() live on api.applications, not app.network — they operate across every application in the account rather than a single website.

Listing every domain

api.applications.domains() returns every domain configured across all of the account’s applications.
const domains = await api.applications.domains();

for (const domain of domains) {
    console.log(domain.app_id, domain.hostname, domain.type); // "subdomain" | "custom"
}
Custom domains are listed first; applications without a web domain are omitted. Results are served from cache and rate limited to 20 requests/60s per user, which does not count toward the per-application network rate limits described above.

Load balancers

api.applications.loadBalancers() groups applications that share a custom domain.
const { limit, balancers } = await api.applications.loadBalancers();

for (const balancer of balancers) {
    console.log(balancer.hostname, balancer.apps.map((app) => app.name));
}
A group with 2 or more apps is an active load balancer: traffic is balanced at the edge with automatic failover when one of the apps is offline. limit is the maximum number of applications that can share one domain on the account’s plan: 2 (Standard), 5 (Pro), 10 (Enterprise). Rate limited to 20 requests/60s per user.