Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Upsun.com Rest Continuous Profiling API
version: '1.0'
contact:
name: Support
url: https://upsun.com/contact-us/
termsOfService: https://upsun.com/trust-center/legal/tos/
description: "# Introduction\n\nUpsun, formerly Platform.sh, is a container-based Platform-as-a-Service. Our main API\nis simply Git. With a single `git push` and a couple of YAML files in\nyour repository you can deploy an arbitrarily complex cluster.\nEvery [**Project**](#tag/Project) can have multiple applications (PHP,\nNode.js, Python, Ruby, Go, etc.) and managed, automatically\nprovisioned services (databases, message queues, etc.).\n\nEach project also comes with multiple concurrent\nlive staging/development [**Environments**](#tag/Environment).\nThese ephemeral development environments\nare automatically created every time you push a new branch or create a\npull request, and each has a full copy of the data of its parent branch,\nwhich is created on-the-fly in seconds.\n\nOur Git implementation supports integrations with third party Git\nproviders such as GitHub, Bitbucket, or GitLab, allowing you to simply\nintegrate Upsun into your existing workflow.\n\n## Using the REST API\n\nIn addition to the Git API, we also offer a REST API that allows you to manage\nevery aspect of the platform, from managing projects and environments,\nto accessing accounts and subscriptions, to creating robust workflows\nand integrations with your CI systems and internal services.\n\nThese API docs are generated from a standard **OpenAPI (Swagger)** Specification document\nwhich you can find here in [YAML](openapispec-upsun.yaml) and in [JSON](openapispec-upsun.json) formats.\n\nThis RESTful API consumes and produces HAL-style JSON over HTTPS,\nand any REST library can be used to access it. On GitHub, we also host\na few API libraries that you can use to make API access easier, such as our\n[PHP API client](https://github.com/upsun/upsun-sdk-php).\n\nIn order to use the API you will first need to have an [Upsun account](https://auth.upsun.com/register/)\nand [create an API Token](https://docs.upsun.com/anchors/cli/api-token/).\n\n# Authentication\n\n## OAuth2\n\nAPI authentication is done with OAuth2 access tokens.\n\n### API tokens\n\nYou can use an API token as one way to get an OAuth2 access token. This\nis particularly useful in scripts, e.g. for CI pipelines.\n\nTo create an API token, go to the \"API Tokens\" section\nof the \"Account Settings\" tab on the [Console](https://console.upsun.com).\n\nTo exchange this API token for an access token, a `POST` request\nmust be made to `https://auth.upsun.com/oauth2/token`.\n\nThe request will look like this in cURL:\n\n<pre>\ncurl -u platform-api-user: \\\n -d 'grant_type=api_token&api_token=<em><b>API_TOKEN</b></em>' \\\n https://auth.upsun.com/oauth2/token\n</pre>\n\nThis will return a \"Bearer\" access token that\ncan be used to authenticate further API requests, for example:\n\n<pre>\n{\n \"access_token\": \"<em><b>abcdefghij1234567890</b></em>\",\n \"expires_in\": 900,\n \"token_type\": \"bearer\"\n}\n</pre>\n\n### Using the Access Token\n\nTo authenticate further API requests, include this returned bearer token\nin the `Authorization` header. For example, to retrieve a list of\n[Projects](#tag/Project)\naccessible by the current user, you can make the following request\n(substituting the dummy token for your own):\n\n<pre>\ncurl -H \"Authorization: Bearer <em><b>abcdefghij1234567890</b></em>\" \\\n https://api.upsun.com/projects\n</pre>\n\n# HAL Links\n\nMost endpoints in the API return fields which defines a HAL\n(Hypertext Application Language) schema for the requested endpoint.\nThe particular objects returns and their contents can vary by endpoint.\nThe payload examples we give here for the requests do not show these\nelements. These links can allow you to create a fully dynamic API client\nthat does not need to hardcode any method or schema.\n\nUnless they are used for pagination we do not show the HAL links in the\npayload examples in this documentation for brevity and as their content\nis contextual (based on the permissions of the user).\n\n## _links Objects\n\nMost endpoints that respond to `GET` requests will include a `_links` object\nin their response. The `_links` object contains a key-object pair labelled `self`, which defines\ntwo further key-value pairs:\n\n* `href` - A URL string referring to the fully qualified name of the returned object. For many endpoints, this will be the direct link to the API endpoint on the region gateway, rather than on the general API gateway. This means it may reference a host of, for example, `eu-2.platform.sh` rather than `api.upsun.com`.\n* `meta` - An object defining the OpenAPI Specification (OAS) [schema object](https://swagger.io/specification/#schemaObject) of the component returned by the endpoint.\n\nThere may be zero or more other fields in the `_links` object resembling fragment identifiers\nbeginning with a hash mark, e.g. `#edit` or `#delete`. Each of these keys\nrefers to a JSON object containing two key-value pairs:\n\n* `href` - A URL string referring to the path name of endpoint which can perform the action named in the key.\n* `meta` - An object defining the OAS schema of the endpoint. This consists of a key-value pair, with the key defining an HTTP method and the value defining the [operation object](https://swagger.io/specification/#operationObject) of the endpoint.\n\nTo use one of these HAL links, you must send a new request to the URL defined\nin the `href` field which contains a body defined the schema object in the `meta` field.\n\nFor example, if you make a request such as `GET /projects/abcdefghij1234567890`, the `_links`\nobject in the returned response will include the key `#delete`. That object\nwill look something like this fragment:\n\n```\n\"#delete\": {\n \"href\": \"/api/projects/abcdefghij1234567890\",\n \"meta\": {\n \"delete\": {\n \"responses\": {\n . . . // Response definition omitted for space\n },\n \"parameters\": []\n }\n }\n}\n```\n\nTo use this information to delete a project, you would then send a `DELETE`\nrequest to the endpoint `https://api.upsun.com/api/projects/abcdefghij1234567890`\nwith no body or parameters to delete the project that was originally requested.\n\n## _embedded Objects\n\nRequests to endpoints which create or modify objects, such as `POST`, `PATCH`, or `DELETE`\nrequests, will include an `_embedded` key in their response. The object\nrepresented by this key will contain the created or modified object. This\nobject is identical to what would be returned by a subsequent `GET` request\nfor the object referred to by the endpoint.\n"
x-logo:
url: https://docs.upsun.com/images/upsun-api.svg
href: https://upsun.com/#section/Introduction
altText: Upsun logo
servers:
- url: '{schemes}://api.upsun.com'
description: The Upsun.com API gateway
variables:
schemes:
default: https
security:
- BearerAuth: []
tags:
- name: Continuous Profiling
paths:
/projects/{projectId}/environments/{envId}/continuous-profiling:
get:
operationId: list_applications
summary: List profiled applications
description: Returns all applications reporting continuous profiling data for the authenticated agent, scoped to the given time range. Each application includes its available profile types (with unit and aggregation metadata) and detected languages
tags:
- Continuous Profiling
parameters:
- name: projectId
in: path
required: true
description: The unique identifier of the Upsun project
schema:
type: string
pattern: '[a-z0-9]+'
example: 22sdxmbrs4lai
- name: envId
in: path
required: true
description: The environment identifier
schema:
type: string
pattern: .+
example: main
- name: from
in: query
description: Start of the time range as a Unix timestamp, defaults to now minus 30 minutes.
schema:
type: integer
format: int64
example: 1700000000
- name: to
in: query
description: End of the time range as a Unix timestamp, defaults to now.
schema:
type: integer
format: int64
example: 1700003600
responses:
'200':
description: Applications listed successfully
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- applications
properties:
applications:
type: object
description: Map of application name to application details
example:
ingester:
name: ingester
profile_types:
cpu:
name: cpu
description: Time spent running on the CPU
title: CPU Time
unit: nanoseconds
aggregation: sum
alloc_objects:
name: alloc_objects
description: Number of objects allocated
title: Allocations
unit: count
aggregation: sum
languages:
- go
admin-pipeline:
name: admin-pipeline
profile_types:
cpu:
name: cpu
description: Time spent running on the CPU
title: CPU Time
unit: nanoseconds
aggregation: sum
wall-time:
name: wall-time
description: Wall clock time spent executing
title: Wall Time
unit: nanoseconds
aggregation: sum
languages:
- php
additionalProperties:
type: object
additionalProperties: false
required:
- name
- profile_types
- languages
properties:
name:
type: string
example: my-app
profile_types:
type: object
description: Map of profile type name to profile type details
example:
cpu:
name: cpu
description: Time spent running on the CPU
title: CPU Time
unit: nanoseconds
aggregation: sum
alloc_objects:
name: alloc_objects
description: Number of objects allocated
title: Allocations
unit: count
aggregation: sum
additionalProperties:
type: object
additionalProperties: false
required:
- name
- description
- title
- unit
- aggregation
properties:
name:
type: string
example: cpu
description:
type: string
example: Time spent running on the CPU
title:
type: string
example: CPU Time
unit:
type: string
example: nanoseconds
aggregation:
type: string
enum:
- avg
- sum
example: sum
languages:
type: array
items:
type: string
example:
- go
- python
'400':
description: Bad request - Invalid parameters. Please consult the API documentation to fix the request parameters.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: integer
example: 400
message:
type: string
example: invalid 'from' parameter
'403':
description: Forbidden - Access denied due to insufficient permissions, or the requested project/environment does not exist (to prevent information disclosure)
'499':
description: Query timeout - The query exceeded the server timeout limit. Please narrow down the query by reducing the time range or adding more specific filters
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: integer
example: 499
message:
type: string
example: Timeout while querying data
/projects/{projectId}/environments/{envId}/continuous-profiling/app/{app}:
get:
operationId: get_application_timeline
summary: Get application timeline
description: Returns timeline data points for the given application and profile type, scoped to the authenticated agent. Points are aggregated at a computed grain (60s to 1h) based on the time range. The response includes the bounded time range, aggregation metadata, and the agent retention period
tags:
- Continuous Profiling
parameters:
- name: projectId
in: path
required: true
description: The unique identifier of the Upsun project
schema:
type: string
pattern: '[a-z0-9]+'
example: 22sdxmbrs4lai
- name: envId
in: path
required: true
description: The environment identifier
schema:
type: string
pattern: .+
example: main
- name: app
in: path
required: true
description: URL-encoded application name
schema:
type: string
pattern: .+
example: my-app
- name: from
in: query
description: Start of the time range as a Unix timestamp, defaults to now minus 30 minutes.
schema:
type: integer
format: int64
example: 1700000000
- name: to
in: query
description: End of the time range as a Unix timestamp, defaults to now.
schema:
type: integer
format: int64
example: 1700003600
- name: profile_type
in: query
description: Profile type to query.
schema:
type: string
enum:
- cpu
- wall-time
- wall
- goroutine
- alloc_objects
- alloc_space
- inuse_objects
- inuse_space
- space
default: null
example: cpu
- $ref: '#/components/parameters/RuntimeMode'
- $ref: '#/components/parameters/RuntimeValues'
- $ref: '#/components/parameters/RuntimeVersionMode'
- $ref: '#/components/parameters/RuntimeVersionValues'
- $ref: '#/components/parameters/RuntimeArchMode'
- $ref: '#/components/parameters/RuntimeArchValues'
- $ref: '#/components/parameters/RuntimeOsMode'
- $ref: '#/components/parameters/RuntimeOsValues'
- $ref: '#/components/parameters/ProbeVersionMode'
- $ref: '#/components/parameters/ProbeVersionValues'
responses:
'200':
description: Timeline data retrieved successfully
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- from
- to
- grain
- unit
- aggregation_type
- retention
- points
properties:
from:
type: integer
format: int64
description: Actual start of the time range as a Unix timestamp
example: 1700000000
to:
type: integer
format: int64
description: Actual end of the time range as a Unix timestamp
example: 1700003600
grain:
type: integer
description: Granularity of data points in seconds
example: 1800
unit:
type: string
description: Unit of the sample values, suffixed with `_per_second` for sum aggregation types
example: nanoseconds_per_second
aggregation_type:
type: string
enum:
- avg
- sum
example: sum
retention:
type: integer
description: Agent retention period in minutes
example: 80640
points:
type: array
items:
type: object
additionalProperties: false
required:
- timestamp
properties:
timestamp:
type: integer
format: int64
example: 1700000000
value:
type: integer
format: int64
description: Aggregated sample value for this time slot. When no profiling data was collected during this slot, the key is entirely absent from the JSON object (not present as null or zero). The frontend should render such points as gaps in the timeline chart, not as zero-value data points
example: 15733333
'400':
description: Bad request - Invalid parameters. Please consult the API documentation to fix the request parameters.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: integer
example: 400
message:
type: string
example: Invalid filters
'403':
description: Forbidden - Access denied due to insufficient permissions, or the requested project/environment does not exist (to prevent information disclosure)
'499':
description: Query timeout - The query exceeded the server timeout limit. Please narrow down the query by reducing the time range or adding more specific filters
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: integer
example: 499
message:
type: string
example: Timeout while querying data
/projects/{projectId}/environments/{envId}/continuous-profiling/app/{app}/merge:
get:
operationId: get_application_merge
summary: Get merged profile
description: 'Returns a merged profile for the given application over the specified time range. The output format is controlled by the `out` query parameter: `pprof` returns a gzipped protobuf with Content-Disposition header, `dot` returns a GraphViz DOT graph, `flamebearerv2` returns JSON flame graph data'
tags:
- Continuous Profiling
parameters:
- name: projectId
in: path
required: true
description: The unique identifier of the Upsun project
schema:
type: string
pattern: '[a-z0-9]+'
example: 22sdxmbrs4lai
- name: envId
in: path
required: true
description: The environment identifier
schema:
type: string
pattern: .+
example: main
- name: app
in: path
required: true
description: URL-encoded application name
schema:
type: string
pattern: .+
example: my-app
- name: from
in: query
description: Start of the time range as a Unix timestamp, defaults to now minus 30 minutes.
schema:
type: integer
format: int64
example: 1700000000
- name: to
in: query
description: End of the time range as a Unix timestamp, defaults to now.
schema:
type: integer
format: int64
example: 1700003600
- name: profile_type
in: query
description: Profile type to query.
schema:
type: string
enum:
- cpu
- wall-time
- wall
- goroutine
- alloc_objects
- alloc_space
- inuse_objects
- inuse_space
- space
default: null
example: cpu
- name: out
in: query
description: Output format for the merged profile.
schema:
type: string
enum:
- pprof
- dot
- flamebearerv2
default: null
example: pprof
- $ref: '#/components/parameters/RuntimeMode'
- $ref: '#/components/parameters/RuntimeValues'
- $ref: '#/components/parameters/RuntimeVersionMode'
- $ref: '#/components/parameters/RuntimeVersionValues'
- $ref: '#/components/parameters/RuntimeArchMode'
- $ref: '#/components/parameters/RuntimeArchValues'
- $ref: '#/components/parameters/RuntimeOsMode'
- $ref: '#/components/parameters/RuntimeOsValues'
- $ref: '#/components/parameters/ProbeVersionMode'
- $ref: '#/components/parameters/ProbeVersionValues'
responses:
'200':
description: Merged profile retrieved successfully
content:
application/octet-stream:
schema:
type: string
format: binary
description: Gzipped pprof protobuf when `out=pprof`
text/vnd.graphviz:
schema:
type: string
description: GraphViz DOT graph when `out=dot`
application/json:
schema:
type: object
additionalProperties: false
description: Flame graph JSON when `out=flamebearerv2`
required:
- version
- flamebearer
- metadata
- _profile_type
- _sample_unit
properties:
version:
type: integer
description: Flamebearer format version
example: 1
flamebearer:
type: object
additionalProperties: false
description: Core flame graph data structure containing function names and the hierarchical call tree encoded as levels of 4-tuples
required:
- names
- levels
- numTicks
- maxSelf
properties:
names:
type: array
description: Array of function identifiers referenced by index in `levels`. Each entry is a JSON-encoded location object with `filename`, `name`, and `line` fields
items:
type: string
example: sync/atomic.(*Pointer).Store
example:
- total
- time.now
- sync/atomic.(*Pointer).Store
levels:
type: array
description: Flame graph call tree encoded as levels. Each level is a flat array of 4-tuples `[offset, total, self, name_index]` where `offset` is the gap from the left edge in sample units, `total` is the inclusive sample count, `self` is the exclusive sample count, and `name_index` references the `names` array
items:
type: array
example:
- 0
- 7361350000000
- 5310000000
- 0
items:
type: integer
example: 0
example:
- - 0
- 7361350000000
- 5310000000
- 0
- - 5310000000
- 160000000
- 0
- 1
- 0
- 483950000000
- 0
- 2
numTicks:
type: integer
description: Total number of samples across the entire profile
example: 7361350000000
maxSelf:
type: integer
description: Maximum exclusive (self) sample count across all nodes
example: 333800000000
metadata:
type: object
additionalProperties: false
description: Profile metadata describing the format and sampling configuration
required:
- format
- spyName
- sampleRate
- units
- name
properties:
format:
type: string
description: Profile format. Always `single` for merged profiles (`double` is used for diff profiles)
example: single
spyName:
type: string
description: Name of the profiling agent that collected the data. Always `unknown` for pprof-based profiles
example: unknown
sampleRate:
type: integer
description: Sampling rate in Hz used during profiling
example: 100
units:
type: string
description: Unit of measure for sample values (e.g. `nanoseconds`, `bytes`, `count`)
example: nanoseconds
name:
type: string
description: Human-readable name for the profile
example: merged_profile
timeline:
type:
- object
- 'null'
description: Present for pyroscope flamebearer format compatibility. Always null for merged profiles returned by this endpoint — do not build UI to render this field
additionalProperties: false
required:
- startTime
- samples
- durationDelta
properties:
startTime:
type: integer
format: int64
description: Start of the timeline as a Unix timestamp in seconds
example: 1700000000
samples:
type: array
description: Sequence of sample counts, one per time bucket starting at `startTime` and spaced by `durationDelta`
items:
type: integer
example: 100
example:
- 100
- 200
- 150
durationDelta:
type: integer
format: int64
description: Time interval between consecutive samples in seconds
example: 10
watermarks:
type: object
description: Map of sample index to watermark timestamp
additionalProperties:
type: integer
format: int64
example: null
groups:
type: object
description: Present for pyroscope flamebearer format compatibility. Always an empty object for merged profiles returned by this endpoint — do not build UI to render this field
additionalProperties:
type: object
additionalProperties: false
required:
- startTime
- samples
- durationDelta
properties:
startTime:
type: integer
format: int64
description: Start of the timeline as a Unix timestamp in seconds
example: 1700000000
samples:
type: array
description: Sequence of sample counts, one per time bucket starting at `startTime` and spaced by `durationDelta`
items:
type: integer
example: 100
example:
- 100
- 200
- 150
durationDelta:
type: integer
format: int64
description: Time interval between consecutive samples in seconds
example: 10
watermarks:
type: object
description: Map of sample index to watermark timestamp
additionalProperties:
type: integer
format: int64
example: {}
heatmap:
type:
- object
- 'null'
description: Present for pyroscope flamebearer format compatibility. Always null for merged profiles returned by this endpoint — do not b
# --- truncated at 32 KB (48 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/platform.sh/refs/heads/main/openapi/platform.sh-continuous-profiling-api-openapi.yml