---
title: "Create a new network"
method: POST
path: "/api/v1/networks"
tags: ["Networks"]
---

# Create a new network

`POST /api/v1/networks`

## Request body

- Network
  - `credential_ids` string[], required — Credential IDs associated with this network (hydrated from junction table).
  - `name` string, required
  - `organization_id` string, uuid, required
  - `stale_after_hours` integer, nullable, required — How long a discovery-managed entity on this network may go unobserved before it reads as stale. `None` = unset; callers resolve the effective value through [`Network::stale_after`], never by reading this directly. Network-scoped because staleness is only meaningful relative to scan cadence, and cadence is a property of a network's discoveries.
  - `tags` string[], required
  - `created_at` string, date-time, required
  - `effective_stale_after_hours` integer — `stale_after_hours` with the server's default already applied. Computed, never stored (excluded from `to_params`). Published so the frontend derives staleness from the *same* number the digest uses rather than re-declaring the default in TypeScript, where the two could drift and a host could read stale in the app but current in the digest email.
  - `id` string, uuid, required
  - `updated_at` string, date-time, required

## Response `200`

Network created

- ApiResponseNetwork
  - `data` object
    - `credential_ids` string[], required — Credential IDs associated with this network (hydrated from junction table).
    - `name` string, required
    - `organization_id` string, uuid, required
    - `stale_after_hours` integer, nullable, required — How long a discovery-managed entity on this network may go unobserved before it reads as stale. `None` = unset; callers resolve the effective value through [`Network::stale_after`], never by reading this directly. Network-scoped because staleness is only meaningful relative to scan cadence, and cadence is a property of a network's discoveries.
    - `tags` string[], required
    - `created_at` string, date-time, required
    - `effective_stale_after_hours` integer — `stale_after_hours` with the server's default already applied. Computed, never stored (excluded from `to_params`). Published so the frontend derives staleness from the *same* number the digest uses rather than re-declaring the default in TypeScript, where the two could drift and a host could read stale in the app but current in the digest email.
    - `id` string, uuid, required
    - `updated_at` string, date-time, required
  - `error` string, nullable
  - `meta` ApiMeta, required — API metadata included in all responses
    - `api_version` integer, required — API version (integer, increments on breaking changes)
    - `server_version` string, required — Server version (semver)
  - `success` boolean, required

## Changes

- **2026-07-22** `8d79aa9841a2` — 1 breaking, 2 info
  - added the new required request property `allOf[#/components/schemas/NetworkBase]/stale_after_hours`
  - added the optional property `data/allOf[subschema #2]/effective_stale_after_hours` to the response with the `200` status
  - added the required property `data/allOf[#/components/schemas/NetworkBase]/stale_after_hours` to the response with the `200` status

[Change history](https://skmtc.dev/scanopy/apis/scanopy-api/changes/api/v1/networks/post.md)

---

[API](https://skmtc.dev/scanopy/apis/scanopy-api.md) · [All operations](https://skmtc.dev/scanopy/apis/scanopy-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/scanopy/scanopy-api/revisions/bd76f90aa44b/schema)
