diff --git a/fern/concepts/diagrams.mdx b/fern/concepts/diagrams.mdx
new file mode 100644
index 0000000..5783b18
--- /dev/null
+++ b/fern/concepts/diagrams.mdx
@@ -0,0 +1,23 @@
+# Diagrams
+
+Diagrams are C4 visualisations of your model. They are views onto the underlying model [objects](/core-concepts/model-objects) and [connections](/core-concepts/model-connections). The model data exists independently of any diagram, and the same object can appear in multiple diagrams.
+
+---
+
+## Diagram types
+
+Each diagram type maps to a C4 level of abstraction:
+
+| Type | C4 Level | Description |
+| --- | --- | --- |
+| `context-diagram` | Level 1 | Shows a `system` in the context of its actors and external systems |
+| `app-diagram` | Level 2 | Shows the `app` and `store` containers inside a `system` |
+| `component-diagram` | Level 3 | Shows the `component` objects inside an `app` or `store` |
+
+---
+
+## Related concepts
+
+- [Model Objects](/core-concepts/model-objects)
+- [Flows](/core-concepts/flows)
+- [Versions](/core-concepts/versions)
diff --git a/fern/concepts/domains.mdx b/fern/concepts/domains.mdx
new file mode 100644
index 0000000..9253917
--- /dev/null
+++ b/fern/concepts/domains.mdx
@@ -0,0 +1,34 @@
+# Domains
+
+Domains are named groupings that organise [model objects](/core-concepts/model-objects) into bounded contexts. They map closely to the Domain-Driven Design (DDD).
+
+---
+
+## What a domain is
+
+Every model object in a version belongs to exactly one domain. Domains provide a way to segment a large architecture either by business unit (e.g., `Payments`) or by team ownership (e.g., `platform`).
+
+---
+
+## Creating domains
+
+Create a domain in a version:
+
+
+
+---
+
+## Filtering model objects by domain
+
+Use the `GET` endpoint with query parameter `?filter[domainId]={domainId}` to filter objects.
+
+
+
+This is useful for extracting a bounded-context slice of the architecture for reports or external tools.
+
+---
+
+## Related concepts
+
+- [Model Objects](/core-concepts/model-objects)
+- [Model Connections](/core-concepts/model-connections)
diff --git a/fern/concepts/flows.mdx b/fern/concepts/flows.mdx
new file mode 100644
index 0000000..2048e07
--- /dev/null
+++ b/fern/concepts/flows.mdx
@@ -0,0 +1,19 @@
+# Flows
+
+Flows are step-by-step sequences that trace a path through your architecture model. Useful for documenting user journeys, request paths, data flows, or any scenario where ordering and directionality matter.
+
+---
+
+## What a flow is
+
+A flow lives inside a [diagram](/core-concepts/diagrams) and consists of an ordered list of **steps**. Each step identifies a model [object](/core-concepts/model-objects) or [connection](/core-concepts/model-connections) that participates at that point in the sequence. When viewing a flow in the IcePanel UI, the relevant objects and connections are highlighted in order.
+
+Flows are distinct from model connections: a connection represents a static relationship between two objects, while a flow represents a dynamic sequence that may traverse many objects and connections.
+
+---
+
+## Related concepts
+
+- [Model Objects](/core-concepts/model-objects)
+- [Model Connections](/core-concepts/model-connections)
+- [Diagrams](/core-concepts/diagrams)
diff --git a/fern/concepts/landscapes.mdx b/fern/concepts/landscapes.mdx
new file mode 100644
index 0000000..fd73a31
--- /dev/null
+++ b/fern/concepts/landscapes.mdx
@@ -0,0 +1,75 @@
+# Landscapes
+
+A landscape is the primary workspace in IcePanel. It holds a complete C4 architecture model including all objects, connections, diagrams, flows, and versions.
+
+---
+
+## What a landscape contains
+
+Each landscape is versioned. All models like objects, connections, diagrams, flows, and domains live inside a [version](/core-concepts/versions) of a landscape.
+
+When you create a landscape, IcePanel automatically creates an initial `latest` version that you can modify immediately.
+
+Create a landscape:
+
+
+
+The response returns both the `landscape` and the initial `version` objects.
+
+List all landscapes in your organization:
+
+
+
+---
+
+## URL patterns
+
+Landscape endpoints are available in two forms.
+
+**Organization-scoped** (includes org context, useful when you have the org ID in scope):
+```
+GET /organizations/{organizationId}/landscapes/{landscapeId}
+```
+
+**Landscape-scoped** (shorter, useful when you already know the landscape ID):
+```
+GET /landscapes/{landscapeId}
+```
+
+All version-scoped resources (model objects, diagrams, flows, etc.) use only the landscape-scoped pattern:
+```
+GET /landscapes/{landscapeId}/versions/{versionId}/model/objects
+```
+
+You can also specify `latest` as a shorthand for getting the latest version:
+
+```
+GET /landscapes/{landscapeId}/versions/latest/model/objects
+```
+
+---
+
+## Duplicate vs copy
+
+IcePanel provides two operations for replicating a landscape:
+
+| Operation | Description |
+| --- | --- |
+| **Duplicate** | Creates a full copy of the landscape within the same organization, including all versions and model content |
+| **Copy** | Copies the model content of a specific version into a different target landscape. This is useful for merging two models or seeding a new landscape from an existing one |
+
+Duplicate a landscape:
+
+
+
+Copy to another landscape:
+
+
+
+---
+
+## Related concepts
+
+- [Versions](/core-concepts/versions)
+- [Model Objects](/core-concepts/model-objects)
+- [Diagrams](/core-concepts/diagrams)
diff --git a/fern/concepts/model-connections.mdx b/fern/concepts/model-connections.mdx
new file mode 100644
index 0000000..710643f
--- /dev/null
+++ b/fern/concepts/model-connections.mdx
@@ -0,0 +1,47 @@
+# Model Connections
+
+Model connections are the edges of the model objects in your architecture. They represent relationships, dependencies, API calls, data flows, or any meaningful interaction between two model objects.
+
+---
+
+## Creating connections
+
+
+
+---
+
+## Filtering connections
+
+The `GET /model/connections` endpoint supports filtering:
+
+| Query parameter | Description |
+| --- | --- |
+| `filter[originId]` | Connections starting from a specific object |
+| `filter[targetId]` | Connections ending at a specific object |
+| `filter[viaId]` | Connections passing through a specific object |
+| `filter[direction]` | `outgoing` or `bidirectional` |
+| `filter[status]` | Status lifecycle value |
+| `filter[tagIds][]` | One or more tag IDs |
+| `filter[technologyIds][]` | One or more technology IDs |
+| `filter[labels][key]` | Label key-value pair |
+| `filter[name]` | Partial name match |
+| `filter[linked]` | `true` to return only connections with at least one link |
+
+---
+
+## Status lifecycle
+
+Connections share the same four-state lifecycle as [model objects](/core-concepts/model-objects):
+
+| Status | Description |
+| --- | --- |
+| `live` | Active dependency or relationship |
+| `future` | Planned but not yet implemented |
+| `deprecated` | In use but being phased out |
+| `removed` | Retired, kept for historical reference |
+
+---
+
+## Related concepts
+
+- [Model Objects](/core-concepts/model-objects)
diff --git a/fern/concepts/model-objects.mdx b/fern/concepts/model-objects.mdx
new file mode 100644
index 0000000..bd32e8c
--- /dev/null
+++ b/fern/concepts/model-objects.mdx
@@ -0,0 +1,93 @@
+# Model Objects
+
+Model objects are the nodes in your architecture graph. They represent the actors, systems, services, and components that make up your software architecture.
+
+---
+
+## Object types
+
+IcePanel uses the C4 model's levels of abstraction. Each object type maps to a C4 level:
+
+| Type | C4 Level | Description |
+| --- | --- | --- |
+| `root` | — | The root node of every [domain](/core-concepts/domains). There is exactly one per domain. All top-level systems and actors are children of the root. |
+| `actor` | Level 1 | A person or external role that interacts with your architecture (e.g. "Customer", "Admin") |
+| `system` | Level 1 | A top-level software system (e.g. "IcePanel") |
+| `group` | Level 1 | A visual grouping (e.g. "Worker Pool", "Subnet") |
+| `app` | Level 2 | A deployable unit (container) inside a system: a service, web app, mobile app, or queue |
+| `store` | Level 2 | A persistent data store inside a system: a database, blob store, or cache |
+| `component` | Level 3 | An internal building block inside an `app` or `store` |
+
+---
+
+## The parent–child hierarchy
+
+Model objects form a tree. Every object except `root` has a `parentId` pointing to its parent:
+
+```
+root
+├── actor: Customer
+├── system: Payment Service
+│ ├── app: API Gateway
+│ │ ├── component: Auth Middleware
+│ │ └── component: Rate Limiter
+│ ├── app: Payment Processor
+│ └── store: Transactions DB
+└── system: Auth Platform (external)
+```
+
+---
+
+## Creating objects
+
+To create a new object, specify the `landscapeId` and either the `versionId` or `latest`:
+
+
+---
+
+## Filtering objects
+
+To find the root object (required as `parentId` when creating top-level objects), use the query parameter `?filter[type]=root`
+
+
+
+The `GET /model/objects` endpoint supports the following filters:
+
+| Query parameter | Description |
+| --- | --- |
+| `filter[type]` | Object type |
+| `filter[status]` | Status lifecycle value |
+| `filter[parentId]` | Direct parent ID |
+| `filter[domainId]` | Domain ID |
+| `filter[external]` | `true` / `false` |
+| `filter[tagIds][]` | One or more tag IDs |
+| `filter[teamIds][]` | One or more team IDs |
+| `filter[technologyIds][]` | One or more technology IDs |
+| `filter[labels][key]` | Label key-value pair |
+| `filter[name]` | Partial name match |
+| `filter[linked]` | `true` to return only objects with at least one link |
+
+---
+
+## Status lifecycle
+
+Objects and connections share a four-state lifecycle representing their architectural status:
+
+```
+live → deprecated → removed → future
+```
+
+| Status | Description |
+| --- | --- |
+| `live` | Current, active element |
+| `future` | Planned but not yet built |
+| `deprecated` | Still in use but being phased out |
+| `removed` | Retired, kept for historical reference |
+
+Use the `filter[status]` query parameter to retrieve only objects with a given status.
+
+---
+
+## Related concepts
+
+- [Model Connections](/core-concepts/model-connections)
diff --git a/fern/concepts/organizations.mdx b/fern/concepts/organizations.mdx
new file mode 100644
index 0000000..1574f10
--- /dev/null
+++ b/fern/concepts/organizations.mdx
@@ -0,0 +1,16 @@
+# Organizations
+
+An organization is the top-level model in IcePanel. It owns all landscapes, manages billing, and controls who has access.
+
+---
+
+Every API key and every landscape belongs to exactly one organization. The `organizationId` is the first path parameter you'll need for most operations.
+
+
+
+---
+
+## Related concepts
+
+- [Landscapes](/core-concepts/landscapes)
+- [Versions](/core-concepts/versions)
diff --git a/fern/concepts/overview.mdx b/fern/concepts/overview.mdx
new file mode 100644
index 0000000..292b064
--- /dev/null
+++ b/fern/concepts/overview.mdx
@@ -0,0 +1,98 @@
+---
+title: Core Concepts
+description: Understand the IcePanel data model before building integrations
+---
+
+The IcePanel API is built around a set of concepts called the **Data Model** that you'll see throughout every endpoint.
+
+---
+
+## Key concepts
+
+**[Organization](/core-concepts/organizations)**
+The top-level model for access control. All landscapes and users belong to an organization.
+
+**[Landscape](/core-concepts/landscapes)**
+A self-contained model workspace (like a repository). An organization can have multiple landscapes for different products or teams.
+
+**[Version](/core-concepts/versions)**
+A snapshot of a landscape's model. The `latest` version is the live editable version. Numbered versions are immutable snapshots created at meaningful points in time. All model data is scoped to a version.
+
+**[Domain](/core-concepts/domains)**
+A bounded context that groups related model objects. Every model object belongs to exactly one domain.
+
+**[Model (Object)](/core-concepts/model-objects)**
+A node in the architecture graph. Can be a `system`, `app`, `component`, `store`, `actor`, `group`, or `root`. Objects form a parent–child hierarchy and can carry tags, technology associations, and custom labels.
+
+**[Model (Connection)](/core-concepts/model-connections)**
+A defined relationship between two model objects. Represents a dependency, data flow, or API call.
+
+**[Diagram](/core-concepts/diagrams)**
+A view onto the model. The underlying model objects and connections exist independently of any diagram.
+
+**[Flow](/core-concepts/flows)**
+A step-by-step sequence that traces a path through model objects and connections. Useful for documenting user journeys, request paths, or data flows.
+
+---
+
+## Data Model hierarchy
+
+```
+Organization
+├── Team
+└── Landscape
+ └── Version
+ ├── Domain
+ ├── Model (Object)
+ │ └── Model Objects Children (Recursive)
+ ├── Model (Connection)
+ ├── Flow
+ ├── Comment
+ ├── Draft
+ └── Share Link
+```
+
+Everything beneath a version is **version-scoped**. When you read or write model objects, connections, diagrams, flows, tags, or domains, you always specify both a `landscapeId` and a `versionId`:
+
+```
+/landscapes/{landscapeId}/versions/{versionId}/model/objects
+/landscapes/{landscapeId}/versions/{versionId}/diagrams
+/landscapes/{landscapeId}/versions/{versionId}/flows
+```
+
+Use `latest` to select the live editable version. Use a version ID (e.g. `xqD4yXmqukb1LKaMAAUL`) to select an immutable snapshot.
+
+---
+
+## What to learn next
+
+
+
+ Where all landscapes and users belong to an organization.
+
+
+ Your C4 model workspace. Create, duplicate, and manage landscapes across your organization.
+
+
+ Snapshots and the live `latest` version. Understand how version scoping works across the API.
+
+
+ Bounded contexts that group model objects.
+
+
diff --git a/fern/concepts/versions.mdx b/fern/concepts/versions.mdx
new file mode 100644
index 0000000..bb2c7d8
--- /dev/null
+++ b/fern/concepts/versions.mdx
@@ -0,0 +1,68 @@
+# Versions
+
+IcePanel uses a versioning system to let you maintain a live working model while also capturing point-in-time snapshots for communication and history.
+
+---
+
+## The `latest` version
+
+Every [landscape](/core-concepts/landscapes) has a special version with the ID `latest`. This is the live version where you make changes through the IcePanel UI or the API.
+
+Use `latest` in any version-scoped endpoint:
+
+```
+GET /landscapes/{landscapeId}/versions/latest/model/objects
+POST /landscapes/{landscapeId}/versions/latest/model/objects
+```
+
+---
+
+## Version snapshots
+
+A version snapshot is an immutable copy of the model at a point in time. Snapshots are useful for:
+
+- Marking a release or milestone
+- Sharing a stable view of the architecture with stakeholders
+- Reverting to a known-good state
+
+Create a snapshot from the current state of `latest`:
+
+
+
+Required fields:
+
+| Field | Description |
+| --- | --- |
+| `name` | Version name, e.g. `v2.4.0` or `Q3 2025` |
+| `notes` | Description of what changed in this version |
+| `modelHandleId` | The `handleId` of the root model object to snapshot |
+
+Once created, a snapshot version is read-only. Its ID is a system-generated string (not `latest`).
+
+List all versions for a landscape:
+
+
+
+---
+
+## Version reverts
+
+Roll back a landscape to the state captured in a previous snapshot:
+
+
+
+Required fields:
+
+| Field | Description |
+| --- | --- |
+| `versionId` | The snapshot to revert to |
+| `notes` | Reason for the revert |
+
+A revert creates a new entry in the revert history and replaces the `latest` version with the snapshot state. The snapshot itself is not modified.
+
+---
+
+## Related concepts
+
+- [Landscapes](/core-concepts/landscapes)
+- [Model Objects](/core-concepts/model-objects)
diff --git a/fern/docs.yml b/fern/docs.yml
index 7794091..4cc5cde 100644
--- a/fern/docs.yml
+++ b/fern/docs.yml
@@ -11,7 +11,7 @@ default-language: typescript
experimental:
ai-examples: false
-logo:
+logo:
href: /
dark: assets/logo-dark.svg
light: assets/logo-light.svg
@@ -22,13 +22,13 @@ colors:
light: "#346DDB"
dark: "#346DDB"
background:
- light: "#f3f4f6"
+ light: "#f3f4f6"
dark: "#1b1d20"
typography:
headingsFont:
name: IBM Plex Sans
- paths:
+ paths:
- path: fonts/IBMPlexSans-Bold.ttf
weight: 700
style: normal
@@ -37,29 +37,75 @@ typography:
path: fonts/IBMPlexSans-Regular.ttf
style: normal
+tabs:
+ developer_guide:
+ display-name: Developer Guide
+ icon: book
+ core_concepts:
+ display-name: Core Concepts
+ icon: sitemap
+ api_reference:
+ display-name: API Reference
+ icon: puzzle
+
navigation:
- - section: Introduction
- contents:
- - page: Getting Started
- path: ./introduction/getting-started.mdx
- - page: Guides
- path: ./introduction/guides.mdx
- - page: Use Cases
- path: ./introduction/use-cases.mdx
- - page: Rate Limits
- path: ./introduction/rate-limits.mdx
- - api: API Reference
- snippets:
- typescript: '@icepanel/sdk'
- java: 'com.icepanel:sdk'
- audiences:
- - public
+ - tab: developer_guide
+ layout:
+ - section: Getting Started
+ contents:
+ - page: Introduction
+ path: ./introduction/what-is-icepanel.mdx
+ - page: Quickstart
+ path: ./introduction/quickstart.mdx
+ - page: Rate limits
+ path: ./introduction/rate-limits.mdx
+
+ - section: How-to Guides
+ contents:
+ - page: Create model objects
+ path: ./guides/create-objects.mdx
+ - page: Export objects and relationships
+ path: ./guides/export-objects.mdx
+ - page: Update model descriptions
+ path: ./guides/update-descriptions.mdx
+ - page: Create landscape versions
+ path: ./guides/create-versions.mdx
+
+ - tab: core_concepts
+ layout:
+ - page: Overview
+ path: ./concepts/overview.mdx
+ - page: Organizations
+ path: ./concepts/organizations.mdx
+ - page: Landscapes
+ path: ./concepts/landscapes.mdx
+ - page: Versions
+ path: ./concepts/versions.mdx
+ - page: Domains
+ path: ./concepts/domains.mdx
+ - page: Model Objects
+ path: ./concepts/model-objects.mdx
+ - page: Model Connections
+ path: ./concepts/model-connections.mdx
+ - page: Diagrams
+ path: ./concepts/diagrams.mdx
+ - page: Flows
+ path: ./concepts/flows.mdx
+
+ - tab: api_reference
+ layout:
+ - api: API Reference
+ snippets:
+ typescript: '@icepanel/sdk'
+ java: 'com.icepanel:sdk'
+ audiences:
+ - public
-navbar-links:
+navbar-links:
- type: filled
text: "Sign up"
href: "https://app.icepanel.io/user/sign-up"
- - type: minimal
+ - type: minimal
text: "Log in"
href: "https://app.icepanel.io"
diff --git a/fern/guides/create-objects.mdx b/fern/guides/create-objects.mdx
new file mode 100644
index 0000000..0530671
--- /dev/null
+++ b/fern/guides/create-objects.mdx
@@ -0,0 +1,60 @@
+---
+title: Create model objects
+description: Add new objects to your landscape.
+---
+
+This guide shows how to create new objects in your landscape model. Useful for automatically filling out your model from another source.
+
+## Prerequisites
+
+- [IcePanel account](https://app.icepanel.io/user/sign-up)
+- [API key](https://app.icepanel.io)
+
+```bash
+export ICEPANEL_API_KEY='your-api-key'
+export ICEPANEL_ORGANIZATION_ID='your-organization-id'
+```
+
+## Steps
+
+
+
+ Get all landscapes in your organization and select a landscape ID:
+
+
+
+ Note the `id` of the landscape:
+
+ ```bash
+ export ICEPANEL_LANDSCAPE_ID='your-landscape-id'
+ ```
+
+
+
+ Call a `GET` request with query parameter `?filter[type]=root` to find the root model object. Your landscape may have multiple root model objects if you use domains.
+
+
+
+ Note the `id` from the response. This is the `parentId` for any top-level objects you create.
+
+
+
+ Create a new model object as a child of the root:
+
+
+
+
+
+Below is a list of different objects you can create.
+
+### Object types
+
+| Type | Description |
+| --- | --- |
+| `root` | A root object of a landscape. |
+| `system` | A top-level system or bounded context |
+| `app` | An application or service within a system |
+| `component` | A component within an app |
+| `store` | A data store (database, queue, cache) |
+| `actor` | An external user, team, or system |
+| `group` | A logical grouping within a diagram |
diff --git a/fern/guides/create-versions.mdx b/fern/guides/create-versions.mdx
new file mode 100644
index 0000000..851b5ab
--- /dev/null
+++ b/fern/guides/create-versions.mdx
@@ -0,0 +1,33 @@
+# Create landscape versions
+
+Version your landscape and create a snapshot in time on your version timeline. This can be run automatically as part of a build or release pipeline.
+
+## Prerequisites
+
+- [IcePanel account](https://app.icepanel.io/user/sign-up)
+- [API key](https://app.icepanel.io)
+
+```bash
+export ICEPANEL_API_KEY='your-api-key'
+export ICEPANEL_ORGANIZATION_ID='your-organization-id'
+```
+
+## Steps
+
+
+
+ Get all landscapes in your organization and select a landscape ID:
+
+
+
+ Note the `id` of the landscape:
+
+ ```bash
+ export ICEPANEL_LANDSCAPE_ID='your-landscape-id'
+ ```
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/guides/export-objects.mdx b/fern/guides/export-objects.mdx
new file mode 100644
index 0000000..e25249a
--- /dev/null
+++ b/fern/guides/export-objects.mdx
@@ -0,0 +1,47 @@
+# Export objects and relationships
+
+This guide shows how to export IcePanel model objects and relationships. Useful for scenarios like identifying a service's dependencies and ownership during incident response.
+
+IcePanel supports two formats:
+1. **CSV** for importing spreadsheets (does not support [Flows](/core-concepts/flows)).
+2. **JSON** for build pipelines, scripts, and automation (supports [Flows](/core-concepts/flows)).
+
+## Prerequisites
+
+- [IcePanel account](https://app.icepanel.io/user/sign-up)
+- [API key](https://app.icepanel.io)
+
+```bash
+export ICEPANEL_API_KEY='your-api-key'
+export ICEPANEL_ORGANIZATION_ID='your-organization-id'
+```
+
+## Export as CSV
+
+
+
+ Get all landscapes in your organization and select a landscape ID:
+
+
+
+ Note the `id` of the landscape:
+
+ ```bash
+ export ICEPANEL_LANDSCAPE_ID='your-landscape-id'
+ ```
+
+
+
+
+
+
+
+
+
+
+
+## Export as JSON
+
+Export the whole model as JSON which can be easily used as part of a build pipeline, script or automation. This also includes flows which the CSV export does not.
+
+
diff --git a/fern/guides/update-descriptions.mdx b/fern/guides/update-descriptions.mdx
new file mode 100644
index 0000000..1a89d8d
--- /dev/null
+++ b/fern/guides/update-descriptions.mdx
@@ -0,0 +1,43 @@
+# Update descriptions with Markdown
+
+Use the existing Markdown documentation stored in a code repository to populate the descriptions of your IcePanel model objects and connections. This can be automatically updated as part of a build pipeline.
+
+## Prerequisites
+
+- [IcePanel account](https://app.icepanel.io/user/sign-up)
+- [API key](https://app.icepanel.io)
+
+```bash
+export ICEPANEL_API_KEY='your-api-key'
+export ICEPANEL_ORGANIZATION_ID='your-organization-id'
+```
+
+## Steps
+
+
+
+ Get all landscapes in your organization and select a landscape ID:
+
+
+
+ Note the `id` of the landscape:
+
+ ```bash
+ export ICEPANEL_LANDSCAPE_ID='your-landscape-id'
+ ```
+
+
+
+ List all model objects in a landscape:
+
+
+
+ Note the `id` of the object you want to update.
+
+
+
+ Patch the model object with your Markdown description. Replace `modelObjectId` with the object's `id`.
+
+
+
+
\ No newline at end of file
diff --git a/fern/introduction/getting-started.mdx b/fern/introduction/getting-started.mdx
deleted file mode 100644
index e686a38..0000000
--- a/fern/introduction/getting-started.mdx
+++ /dev/null
@@ -1,19 +0,0 @@
-# Introduction
-
-The IcePanel REST API is publicly accessible to write automated scripts or custom integrations with external tools.
-
-Our [OpenAPI 3.1](https://swagger.io/specification/) specification can be found at [api.icepanel.io](https://api.icepanel.io/) and opened by importing it into [Postman](https://learning.postman.com/docs/integrations/available-integrations/working-with-openAPI/).
-
-# Authentication
-
-First, generate an API key on your organization management screen. Make sure to copy your key and set the `X-API-Key` HTTP header on any authenticated requests.
-
-```
-X-API-Key: SH5XAiWtgevC2ZfQym3i:17a9c60035eed62c8f4f195c754ee6972ffc40ce975c5571ec521f463ebefa7f
-```
-
-# Example
-
-See the example below for how to request a list of landscapes.
-
-
\ No newline at end of file
diff --git a/fern/introduction/guides.mdx b/fern/introduction/guides.mdx
deleted file mode 100644
index e5935aa..0000000
--- a/fern/introduction/guides.mdx
+++ /dev/null
@@ -1,36 +0,0 @@
-## Synchronize IcePanel objects with external resources
-
-If you have objects in IcePanel that also live in other systems/platforms/cloud providers you may want synchronize properties between these systems. For example you could synchronize external links to a resource from your IcePanel model.
-
-To do this, we recommend using a script to populate/synchronize properties in IcePanel.
-
-### Configure labels on the resource
-
-First, use the labels property to store the identifier of your external resource in the IcePanel object.
-
-```
-curl -X PATCH https://api.icepanel.io/v1/landscapes/{landscapeId}/versions/latest/model/objects/{modelObjectId} \
- -H 'Content-Type: application/json' \
- -H 'X-API-Key {apiKey}' \
- -d '{"labels": {"cloudId": "xxxxxxxxxx"}}'
-```
-
-Labels are only for use in the IcePanel API and are not available on the UI.
-
-### Use labels to update the resource
-
-Once each object has the `cloudId` label assigned you can use that field to reverse lookup the coresponding IcePanel object.
-
-```
-curl -g 'https://api.icepanel.io/v1/landscapes/{landscapeId}/versions/latest/model/objects?filter[labels][cloudId]=xxxxxxxxxx' \
- -H 'X-API-Key {apiKey}'
-```
-
-Once the object has been retrieved, you can use the update endpoint to upsert the link URL to the resource, optionally specifying a friendly name for the UI.
-
-```
-curl -X PATCH https://api.icepanel.io/v1/landscapes/{landscapeId}/versions/latest/model/objects/{modelObjectId} \
- -H 'Content-Type: application/json' \
- -H 'X-API-Key {apiKey}' \
- -d '{"links": {"$add": { "xxxxxxxxxx": { "customName": "Cloud Resource", "url": "https://console.cloud.google.com/run" } } } }'
-```
diff --git a/fern/introduction/quickstart.mdx b/fern/introduction/quickstart.mdx
new file mode 100644
index 0000000..4e7bfe2
--- /dev/null
+++ b/fern/introduction/quickstart.mdx
@@ -0,0 +1,414 @@
+---
+title: Quickstart
+description: Make your first API call to IcePanel
+---
+
+In this example, we'll walk through IcePanel's data model by listing landscapes, viewing model objects, and finding their model connections.
+
+## Prerequisites
+
+- [IcePanel account](https://app.icepanel.io/user/sign-up)
+- [API key](https://app.icepanel.io)
+
+## Call the API
+
+
+
+ Go to **Profile settings** -> **API keys** -> **Create API key** and create a new key.
+
+
+ For future sessions, store it in a `~/.zshrc` or `~/.bashrc`
+ ```bash
+ export ICEPANEL_API_KEY='your-api-key'
+ ```
+ Then run `source ~/.zshrc` (or `~/.bashrc`) to apply immediately.
+
+
+
+
+ This is the top-level model for access control. Landscapes and users belong to an organization.
+
+
+ ```typescript title="TypeScript"
+ import { IcePanelClient } from "@icepanel/sdk";
+
+ async function main() {
+ const client = new IcePanelClient({
+ apiKey: "your-api-key",
+ apiVersion: "v1",
+ });
+ const response = await client.organizations.list({});
+ console.log(response);
+ }
+ main();
+ ```
+
+ ```bash title="cURL"
+ curl "https://api.icepanel.io/v1/organizations" \
+ -H "X-API-Key: $ICEPANEL_API_KEY"
+ ```
+
+ ```python title="Python"
+ import requests
+
+ url = "https://api.icepanel.io/v1/organizations"
+ headers = {"X-API-Key": "your-api-key"}
+ response = requests.get(url, headers=headers)
+ print(response.json())
+ ```
+
+ ```csharp title="C#"
+ using RestSharp;
+
+ var client = new RestClient("https://api.icepanel.io/v1/organizations");
+ var request = new RestRequest();
+ request.AddHeader("X-API-Key", "your-api-key");
+ RestResponse response = client.Execute(request);
+ Console.WriteLine(response.Content);
+ ```
+
+ ```go title="Go"
+ package main
+
+ import (
+ "fmt"
+ "net/http"
+ "io"
+ )
+
+ func main() {
+ url := "https://api.icepanel.io/v1/organizations"
+
+ req, _ := http.NewRequest("GET", url, nil)
+ req.Header.Add("X-API-Key", "your-api-key")
+
+ res, _ := http.DefaultClient.Do(req)
+ defer res.Body.Close()
+ body, _ := io.ReadAll(res.Body)
+
+ fmt.Println(string(body))
+ }
+ ```
+
+ ```java title="Java"
+ package com.example.usage;
+
+ import com.icepanel.IcePanelClient;
+ import com.icepanel.types.OrganizationsListRequest;
+
+ public class Example {
+ public static void main(String[] args) {
+ IcePanelClient client = IcePanelClient
+ .builder()
+ .apiKey("your-api-key")
+ .build();
+
+ var response = client.organizations().list(
+ OrganizationsListRequest.builder().build()
+ );
+ System.out.println(response);
+ }
+ }
+ ```
+
+
+ Note the `id` field. This is your `organizationId`.
+
+
+
+ A workspace within an organization (like a repository).
+
+
+ ```typescript title="TypeScript"
+ import { IcePanelClient } from "@icepanel/sdk";
+
+ async function main() {
+ const client = new IcePanelClient({
+ apiKey: "your-api-key",
+ apiVersion: "v1",
+ });
+ const response = await client.organizations.landscapes.list({
+ organizationId: "organizationId"
+ });
+ console.log(response);
+ }
+ main();
+ ```
+
+ ```bash title="cURL"
+ curl "https://api.icepanel.io/v1/organizations/$ICEPANEL_ORGANIZATION_ID/landscapes" \
+ -H "X-API-Key: $ICEPANEL_API_KEY"
+ ```
+
+ ```python title="Python"
+ import requests
+
+ url = "https://api.icepanel.io/v1/organizations/organizationId/landscapes"
+ headers = {"X-API-Key": "your-api-key"}
+ response = requests.get(url, headers=headers)
+ print(response.json())
+ ```
+
+ ```csharp title="C#"
+ using RestSharp;
+
+ var client = new RestClient("https://api.icepanel.io/v1/organizations/organizationId/landscapes");
+ var request = new RestRequest();
+ request.AddHeader("X-API-Key", "your-api-key");
+ RestResponse response = client.Execute(request);
+ Console.WriteLine(response.Content);
+ ```
+
+ ```go title="Go"
+ package main
+
+ import (
+ "fmt"
+ "net/http"
+ "io"
+ )
+
+ func main() {
+ url := "https://api.icepanel.io/v1/organizations/organizationId/landscapes"
+
+ req, _ := http.NewRequest("GET", url, nil)
+ req.Header.Add("X-API-Key", "your-api-key")
+
+ res, _ := http.DefaultClient.Do(req)
+ defer res.Body.Close()
+ body, _ := io.ReadAll(res.Body)
+
+ fmt.Println(string(body))
+ }
+ ```
+
+ ```java title="Java"
+ package com.example.usage;
+
+ import com.icepanel.IcePanelClient;
+ import com.icepanel.organizations.types.OrganizationLandscapesListRequest;
+
+ public class Example {
+ public static void main(String[] args) {
+ IcePanelClient client = IcePanelClient
+ .builder()
+ .apiKey("your-api-key")
+ .build();
+
+ var response = client.organizations().landscapes().list(
+ OrganizationLandscapesListRequest.builder()
+ .organizationId("organizationId")
+ .build()
+ );
+ System.out.println(response);
+ }
+ }
+ ```
+
+
+ Note the `id` field. This is your `landscapeId`.
+
+
+
+ An object within your landscape. It can be a `system`, `app`, `component`, `store`, `actor`, `group`, or `root`.
+
+
+ ```typescript title="TypeScript"
+ import { IcePanelClient } from "@icepanel/sdk";
+
+ async function main() {
+ const client = new IcePanelClient({
+ apiKey: "your-api-key",
+ apiVersion: "v1",
+ });
+ const response = await client.model.objects.list({
+ landscapeId: "landscapeId",
+ versionId: "latest"
+ });
+ console.log(response);
+ }
+ main();
+ ```
+
+ ```bash title="cURL"
+ curl "https://api.icepanel.io/v1/landscapes/$ICEPANEL_LANDSCAPE_ID/versions/latest/model/objects" \
+ -H "X-API-Key: $ICEPANEL_API_KEY"
+ ```
+
+ ```python title="Python"
+ import requests
+
+ url = "https://api.icepanel.io/v1/landscapes/landscapeId/versions/latest/model/objects"
+ headers = {"X-API-Key": "your-api-key"}
+ response = requests.get(url, headers=headers)
+ print(response.json())
+ ```
+
+ ```csharp title="C#"
+ using RestSharp;
+
+ var client = new RestClient("https://api.icepanel.io/v1/landscapes/landscapeId/versions/latest/model/objects");
+ var request = new RestRequest();
+ request.AddHeader("X-API-Key", "your-api-key");
+ RestResponse response = client.Execute(request);
+ Console.WriteLine(response.Content);
+ ```
+
+ ```go title="Go"
+ package main
+
+ import (
+ "fmt"
+ "net/http"
+ "io"
+ )
+
+ func main() {
+ url := "https://api.icepanel.io/v1/landscapes/landscapeId/versions/latest/model/objects"
+
+ req, _ := http.NewRequest("GET", url, nil)
+ req.Header.Add("X-API-Key", "your-api-key")
+
+ res, _ := http.DefaultClient.Do(req)
+ defer res.Body.Close()
+ body, _ := io.ReadAll(res.Body)
+
+ fmt.Println(string(body))
+ }
+ ```
+
+ ```java title="Java"
+ package com.example.usage;
+
+ import com.icepanel.IcePanelClient;
+ import com.icepanel.model.types.ModelObjectsListRequest;
+
+ public class Example {
+ public static void main(String[] args) {
+ IcePanelClient client = IcePanelClient
+ .builder()
+ .apiKey("your-api-key")
+ .build();
+
+ var response = client.model().objects().list(
+ ModelObjectsListRequest.builder()
+ .landscapeId("landscapeId")
+ .versionId("latest")
+ .build()
+ );
+ System.out.println(response);
+ }
+ }
+ ```
+
+
+ Note the `id` of any object. This is your `modelObjectId`.
+
+
+
+ A defined relationship between two model objects. We'll list model connections where `originId = modelObjectId`.
+
+
+ ```typescript title="TypeScript"
+ import { IcePanelClient } from "@icepanel/sdk";
+
+ async function main() {
+ const client = new IcePanelClient({
+ apiKey: "your-api-key",
+ apiVersion: "v1",
+ });
+ const response = await client.model.connections.list({
+ landscapeId: "landscapeId",
+ versionId: "latest",
+ filter: { originId: "modelObjectId" }
+ });
+ console.log(response);
+ }
+ main();
+ ```
+
+ ```bash title="cURL"
+ curl --globoff "https://api.icepanel.io/v1/landscapes/$ICEPANEL_LANDSCAPE_ID/versions/latest/model/connections?filter[originId]=modelObjectId" \
+ -H "X-API-Key: $ICEPANEL_API_KEY"
+ ```
+
+ ```python title="Python"
+ import requests
+
+ url = "https://api.icepanel.io/v1/landscapes/landscapeId/versions/latest/model/connections"
+ params = {"filter[originId]": "modelObjectId"}
+ headers = {"X-API-Key": "your-api-key"}
+ response = requests.get(url, headers=headers, params=params)
+ print(response.json())
+ ```
+
+ ```csharp title="C#"
+ using RestSharp;
+
+ var client = new RestClient("https://api.icepanel.io/v1/landscapes/landscapeId/versions/latest/model/connections");
+ var request = new RestRequest();
+ request.AddHeader("X-API-Key", "your-api-key");
+ request.AddQueryParameter("filter[originId]", "modelObjectId");
+ RestResponse response = client.Execute(request);
+ Console.WriteLine(response.Content);
+ ```
+
+ ```go title="Go"
+ package main
+
+ import (
+ "fmt"
+ "net/http"
+ "io"
+ )
+
+ func main() {
+ url := "https://api.icepanel.io/v1/landscapes/landscapeId/versions/latest/model/connections?filter[originId]=modelObjectId"
+
+ req, _ := http.NewRequest("GET", url, nil)
+ req.Header.Add("X-API-Key", "your-api-key")
+
+ res, _ := http.DefaultClient.Do(req)
+ defer res.Body.Close()
+ body, _ := io.ReadAll(res.Body)
+
+ fmt.Println(string(body))
+ }
+ ```
+
+ ```java title="Java"
+ package com.example.usage;
+
+ import com.icepanel.IcePanelClient;
+ import com.icepanel.model.types.ModelConnectionsListRequest;
+ import com.icepanel.types.ModelConnectionFilter;
+
+ public class Example {
+ public static void main(String[] args) {
+ IcePanelClient client = IcePanelClient
+ .builder()
+ .apiKey("your-api-key")
+ .build();
+
+ var response = client.model().connections().list(
+ ModelConnectionsListRequest.builder()
+ .landscapeId("landscapeId")
+ .versionId("latest")
+ .filter(ModelConnectionFilter.builder()
+ .originId(ModelConnectionFilter.OriginId.of("modelObjectId"))
+ .build())
+ .build()
+ );
+ System.out.println(response);
+ }
+ }
+ ```
+
+
+
+
+## Next steps
+
+- [Create model objects](/developer-guide/how-to-guides/create-model-objects) Add new objects to your landscape.
+- [Core Concepts](/core-concepts/overview) Learn the IcePanel data model
+- [API Reference](/api-reference) Explore the IcePanel REST API
diff --git a/fern/introduction/rate-limits.mdx b/fern/introduction/rate-limits.mdx
index 2a6a422..6a95ba6 100644
--- a/fern/introduction/rate-limits.mdx
+++ b/fern/introduction/rate-limits.mdx
@@ -1,7 +1,23 @@
-We apply the following rate limits to our REST API which are the same for all environments.
+# Rate limits
-| Endpoints | Methods | Limit |
-| -------- | -------- | ------- |
+We apply the following rate limits to our REST API. Limits are the same for all environments.
+
+| Endpoints | Methods | Limit |
+| --- | --- | --- |
| `/user/*` | `POST` | 10 per minute |
-| `/*` | `GET` `HEAD` | 2,400 per minute |
+| `/*` | `GET` `HEAD` | 2,400 per minute |
| `/*` | `POST` `PUT` `PATCH` `DELETE` | 60 per minute |
+
+---
+
+## Handling rate limit errors
+
+When you exceed a limit, the API returns a `429 Too Many Requests` response with a JSON error body:
+
+```json
+{
+ "message": "Too Many Requests"
+}
+```
+
+Check the `Retry-After` response header to see how many seconds to wait before retrying.
diff --git a/fern/introduction/use-cases.mdx b/fern/introduction/use-cases.mdx
deleted file mode 100644
index 814f67d..0000000
--- a/fern/introduction/use-cases.mdx
+++ /dev/null
@@ -1,67 +0,0 @@
-## Export objects and relationships
-
-The object and relationship data that IcePanel stores as part of the model has great uses. For example informing an incident response team about up and downstream dependencies of a service as well as which team owns the service.
-
-Export objects and connections in CSV format which is great for importing to spreadsheets.
-
-```
-curl https://api.icepanel.io/v1/landscapes/{landscapeId}/versions/latest/model/objects/export/csv
-
-curl https://api.icepanel.io/v1/landscapes/{landscapeId}/versions/latest/model/connections/export/csv
-```
-
-Export the whole model as JSON which can be easily used as part of a build pipeline, script or automation. This also includes flows which the CSV export does not.
-
-```
-curl https://api.icepanel.io/v1/landscapes/{landscapeId}/versions/latest/export/json
-```
-
-## Update model descriptions with Markdown
-
-Use the existing Markdown documentation stored in a code repository to populate the descriptions of your IcePanel model objects and connections. This can be automatically updated as part of a build pipeline.
-
-First fetch a list of the model objects that exist in your landscape and find the identifier to update.
-
-```
-curl https://api.icepanel.io/v1/landscapes/{landscapeId}/versions/latest/model/objects
-```
-
-Then patch the model object identifier with your Markdown description.
-
-```
-curl -X PATCH https://api.icepanel.io/v1/landscapes/{landscapeId}/versions/latest/model/objects/{modelObjectId} \
- -H 'X-API-Key {apiKey}' \
- -d '{"description": "# Heading\nbody"}'
-```
-
-## Create model objects
-
-Create objects in your model, great for automatically filling out your model from another source.
-
-First use a `GET` request to find the root model object, your landscape may have multiple root model objects if you use domains.
-
-```
-curl -g 'https://api.icepanel.io/v1/landscapes/{landscapeId}/versions/latest/model/objects?filter[type]=root' \
- -H 'Content-Type: application/json' \
- -H 'X-API-Key {apiKey}'
-```
-
-Once you've found the root model object pass the id to the `parentId` property of `POST` request to create a model objects inside it.
-
-```
-curl -X POST https://api.icepanel.io/v1/landscapes/{landscapeId}/versions/latest/model/objects \
- -H 'Content-Type: application/json' \
- -H 'X-API-Key {apiKey}' \
- -d '{"name": "New system", "type": "system", "parentId": "{parentId}"}'
-```
-
-## Create a version of your landscape
-
-Version your landscape and create a snapshot in time on your version timeline. This can be run automatically as part of a build or release pipeline.
-
-```
-curl -X POST https://api.icepanel.io/v1/landscapes/{landscapeId}/versions \
- -H 'Content-Type: application/json' \
- -H 'X-API-Key {apiKey}' \
- -d '{"name": "1.0", "notes": "Version 1.0", "modelHandleId": null}'
-```
diff --git a/fern/introduction/what-is-icepanel.mdx b/fern/introduction/what-is-icepanel.mdx
new file mode 100644
index 0000000..85870c1
--- /dev/null
+++ b/fern/introduction/what-is-icepanel.mdx
@@ -0,0 +1,35 @@
+# Introduction
+
+IcePanel is a collaborative diagramming and modelling tool for software architecture.
+
+IcePanel is built around the [C4 model](https://c4model.com/).
+
+Our [OpenAPI 3.1](https://swagger.io/specification/) spec can be found at [api.icepanel.io](https://api.icepanel.io/) and imported into [Postman](https://learning.postman.com/docs/integrations/available-integrations/working-with-openAPI/).
+
+JSON Schemas for IcePanel data types are available at `/v1/schemas/{schemaName}`, for example [`https://api.icepanel.io/v1/schemas/LandscapeImportData`](https://api.icepanel.io/v1/schemas/LandscapeImportData). These can be used to validate or generate typed data structures against the IcePanel API.
+
+---
+
+
+
+ Make your first API call to IcePanel.
+
+
+ Learn more about the IcePanel data model.
+
+
+ Use the IcePanel REST API to automate workflows and integrate with external tools.
+
+