> ## Documentation Index
> Fetch the complete documentation index at: https://developer.upsun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Using the Upsun API

export const PostMeta = ({data = {}}) => {
  const {author, date, image} = data;
  const authors = Array.isArray(author) ? author : author ? [author] : [];
  const resolveAuthor = slug => {
    const entry = AUTHOR_MAP[slug] || ({});
    const name = entry.name || slug;
    const github = entry.github || null;
    const linkedin = entry.linkedin || null;
    const url = github ? `https://github.com/${github}` : linkedin || null;
    const avatarUrl = github ? `https://github.com/${github}.png?size=64` : null;
    return {
      name,
      url,
      avatarUrl
    };
  };
  const formattedDate = date ? new Date(date).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  }) : null;
  if (!image && authors.length === 0 && !formattedDate) return null;
  const AUTHOR_MAP = {
    "aaron-collier": {
      "name": "Aaron Collier"
    },
    "aaron-dudenhofer": {
      "name": "Aaron Dudenhofer"
    },
    "aaron-porter": {
      "name": "Aaron Porter"
    },
    "adriaan-odendaal": {
      "name": "Adriaan Odendaal"
    },
    "ajmal": {
      "name": "Ajmal Siddiqui"
    },
    "akalipetis": {
      "name": "Antonis Kalipetis"
    },
    "alexander-varwijk": {
      "name": "Alexander Varwijk"
    },
    "alicia-bevilacqua": {
      "name": "Alicia Bevilacqua"
    },
    "amelie-deguerry": {
      "name": "Amelie Deguerry"
    },
    "anacidre": {
      "name": "Ana Cidre",
      "linkedin": "https://www.linkedin.com/in/ana-cidre"
    },
    "andoni": {
      "name": "Andoni Auzmendi"
    },
    "andrei-taranu": {
      "name": "Andrei (Alex) Taranu",
      "linkedin": "https://www.linkedin.com/in/andrei-alex-taranu/"
    },
    "andrew-baxter": {
      "name": "Andrew Baxter"
    },
    "andrew-melck": {
      "name": "Andrew Melck"
    },
    "antoine-crochet-damais": {
      "name": "Antoine Crochet Damais"
    },
    "augustin-delaporte": {
      "name": "Augustin Delaporte",
      "linkedin": "https://www.linkedin.com/in/augustindelaporte/"
    },
    "branislav-bujisic": {
      "name": "Branislav Bujisic"
    },
    "carl-smith": {
      "name": "Carl Smith"
    },
    "caroline-leroy": {
      "name": "Caroline Leroy"
    },
    "cati-mayer": {
      "name": "Cati Mayer"
    },
    "catplat": {
      "name": "C Trinkwon"
    },
    "ceelolulu": {
      "name": "Celeste van der Watt"
    },
    "chadwcarlson": {
      "name": "Chad Carlson",
      "github": "chadwcarlson",
      "linkedin": "https://www.linkedin.com/in/chadwcarlson"
    },
    "chris-ward": {
      "name": "Chris Ward"
    },
    "chris-yates": {
      "name": "Chris Yates"
    },
    "christian-sieber": {
      "name": "Christian Sieber"
    },
    "christopher-lockheardt": {
      "name": "Christopher Lockheardt"
    },
    "christopher-skene": {
      "name": "Christopher Skene"
    },
    "chuck-morgan": {
      "name": "Chuck Morgan"
    },
    "corey-dockendorf": {
      "name": "Corey Dockendorf"
    },
    "crell": {
      "name": "Crell"
    },
    "damz": {
      "name": "Damz"
    },
    "dan-morrison": {
      "name": "Dan Morrison"
    },
    "davidbonachera": {
      "name": "David Bonachera",
      "github": "davidbonachera",
      "linkedin": "https://www.linkedin.com/in/davidbonachera"
    },
    "dereliahmet1": {
      "name": "Ahmet Faruk Dereli"
    },
    "devicezero": {
      "name": "Jonas Kröger",
      "github": "devicezero",
      "linkedin": "https://www.linkedin.com/in/jonaskroeger/"
    },
    "doug-goldberg": {
      "name": "Doug Goldberg"
    },
    "duncan-naves": {
      "name": "Duncan Naves",
      "github": "duncannaves",
      "linkedin": "https://www.linkedin.com/in/duncan-naves-a94423aa"
    },
    "erika-bustamante": {
      "name": "Erika Bustamante"
    },
    "fabpot": {
      "name": "Fabien Potencier"
    },
    "flovntp": {
      "name": "Florent Huck",
      "github": "flovntp",
      "linkedin": "https://www.linkedin.com/in/florenthuck"
    },
    "fred-plais": {
      "name": "Fred Plais"
    },
    "gauthier-garnier": {
      "name": "Gauthier Garnier"
    },
    "gilzow": {
      "name": "Paul Gilzow"
    },
    "gmoigneu": {
      "name": "Guillaume Moigneu",
      "github": "gmoigneu",
      "linkedin": "https://www.linkedin.com/in/guillaumemoigneu/"
    },
    "gregqualls": {
      "name": "Greg Qualls"
    },
    "guguss": {
      "name": "Augustin Delaporte"
    },
    "haylee-millar": {
      "name": "Haylee Millar"
    },
    "ivana-kotur": {
      "name": "Ivana Kotur"
    },
    "jackrabbithanna": {
      "name": "Mark Hanna"
    },
    "jared-wright": {
      "name": "Jared Wright",
      "github": "jww-sh",
      "linkedin": "https://www.linkedin.com/in/jaredwaynewright"
    },
    "jessica-orozco": {
      "name": "Jessica Orozco"
    },
    "joey-stanford": {
      "name": "Joey Stanford"
    },
    "john-grubb": {
      "name": "John Grubb"
    },
    "jonas-kruger": {
      "name": "Jonas Kruger"
    },
    "kathryn-frazer": {
      "name": "Kathryn Frazer"
    },
    "kemiojo": {
      "name": "Kemi Elizabeth Ojogbede"
    },
    "kieronsambrook-smith": {
      "name": "Kieronsambrook Smith"
    },
    "laurent-arnoud": {
      "name": "Laurent Arnoud"
    },
    "letoya-boyne": {
      "name": "Letoya Boyne"
    },
    "lolautruche": {
      "name": "Jérôme Vieilledent"
    },
    "lyly-lepinay": {
      "name": "Lyly Lepinay"
    },
    "manauwar-alam": {
      "name": "Manauwar Alam"
    },
    "marc-antoine-porri": {
      "name": "Marc Antoine Porri"
    },
    "maria-antinkaapo": {
      "name": "Maria Antinkaapo"
    },
    "maria-de-anton": {
      "name": "Maria De Anton"
    },
    "mark-dorison": {
      "name": "Mark Dorison"
    },
    "markus-hausammann": {
      "name": "Markus Hausammann"
    },
    "mary-thomas": {
      "name": "Mary Thomas"
    },
    "mathias-bolt-lesniak": {
      "name": "Mathias Bolt Lesniak"
    },
    "mathieu-strauch": {
      "name": "Mathieu Strauch"
    },
    "matthias-van-woensel": {
      "name": "Matthias Van Woensel",
      "linkedin": "https://www.linkedin.com/in/matthias-van-woensel-267a069"
    },
    "michael-sharp": {
      "name": "Michael Sharp"
    },
    "mupsi": {
      "name": "Marine Gandy"
    },
    "natalie-harper": {
      "name": "Natalie Harper"
    },
    "ngommenginger": {
      "name": "Nicolas Gommenginger",
      "linkedin": "https://www.linkedin.com/in/nicolas-gommenginger"
    },
    "nicholas-bennison": {
      "name": "Nicholas Bennison"
    },
    "nicholas-vahalik": {
      "name": "Nicholas Vahalik"
    },
    "nick-hardiman": {
      "name": "Nick Hardiman"
    },
    "nickanderegg": {
      "name": "Nickanderegg"
    },
    "nicolas-grekas": {
      "name": "Nicolas Grekas",
      "github": "nicolas-grekas",
      "linkedin": "https://www.linkedin.com/in/nicolasgrekas/"
    },
    "niti-malwade": {
      "name": "Niti Malwade"
    },
    "opensocialteam": {
      "name": "Opensocialteam"
    },
    "ori-pekelman": {
      "name": "Ori Pekelman"
    },
    "otavio-santana": {
      "name": "Otavio Santana"
    },
    "palwandi": {
      "name": "Pawan Alwandi",
      "github": "pawpy",
      "linkedin": "https://www.linkedin.com/in/pawanalwandi"
    },
    "patrick-boest": {
      "name": "Patrick Boest"
    },
    "patrick-dawkins": {
      "name": "Patrick Dawkins",
      "github": "pjcdawkins",
      "linkedin": "https://www.linkedin.com/in/patrickdawkins"
    },
    "patrick-klima": {
      "name": "Patrick Klima"
    },
    "pjcdawkins": {
      "name": "Pjcdawkins"
    },
    "prineet-kaurbhurji": {
      "name": "Prineet Kaurbhurji"
    },
    "quentin-sinig": {
      "name": "Quentin Sinig"
    },
    "ralt": {
      "name": "Florian Margaine",
      "github": "ralt",
      "linkedin": "https://www.linkedin.com/in/florian-margaine-43971136"
    },
    "ramanathanramakrishnamurthy": {
      "name": "Ramanathanramakrishnamurthy"
    },
    "remi-lejeune": {
      "name": "Rémi Lejeune"
    },
    "ribel": {
      "name": "Taras Kruts"
    },
    "robert-douglass": {
      "name": "Robert Douglass"
    },
    "rudy-weber": {
      "name": "Rudy Weber"
    },
    "ryan-hicks": {
      "name": "Ryan Hicks"
    },
    "sabri-helal": {
      "name": "Sabri Helal"
    },
    "savannah-bergeron": {
      "name": "Savannah Bergeron"
    },
    "shannon-vettes": {
      "name": "Shannon Vettes"
    },
    "shawn-ogasawara": {
      "name": "Shawn Ogasawara",
      "linkedin": "https://www.linkedin.com/in/shawn-ogasawara-83a9a0/"
    },
    "shawna-spoor": {
      "name": "Shawna Spoor"
    },
    "shedrack-akintayo": {
      "name": "Shedrack Akintayo"
    },
    "simon-ruggier": {
      "name": "Simon Ruggier"
    },
    "sophie-van-der-kindere": {
      "name": "Sophie Van Der Kindere"
    },
    "stefanos-thampis": {
      "name": "Stefanos Thampis"
    },
    "stephen-weinberg": {
      "name": "Stephen Weinberg"
    },
    "sukhman-virk": {
      "name": "Sukhman Virk"
    },
    "sumaira-nazir": {
      "name": "Sumaira Nazir"
    },
    "sumer": {
      "name": "Sümer Cip"
    },
    "syed-raza": {
      "name": "Syed Raza"
    },
    "tamara-bacchia": {
      "name": "Tamara Bacchia"
    },
    "tara-arnold": {
      "name": "Tara Arnold"
    },
    "theosakamg": {
      "name": "Mickael Gaillard",
      "github": "theosakamg"
    },
    "thomasdiluccio": {
      "name": "Thomas di Luccio"
    },
    "tim-anderson": {
      "name": "Tim Anderson"
    },
    "tom-helmer-hansen": {
      "name": "Tom Helmer Hansen"
    },
    "tylermills": {
      "name": "Tyler Mills"
    },
    "upsun": {
      "name": "Upsun"
    },
    "veronika-tolkachova": {
      "name": "Veronika Tolkachova",
      "linkedin": "https://www.linkedin.com/in/veronika-tolkachova-169167a2"
    },
    "vince-parker": {
      "name": "Vince Parker"
    },
    "vinnie-russo": {
      "name": "Vincenzo Russo"
    },
    "vrobert78": {
      "name": "Vincent Robert",
      "github": "vrobert78",
      "linkedin": "https://www.linkedin.com/in/vincent-robert-498a883"
    },
    "yuriy-babenko": {
      "name": "Yuriy Babenko"
    },
    "yuriy-gerasimov": {
      "name": "Yuriy Gerasimov"
    }
  };
  return <div className="post-meta">
      {(authors.length > 0 || formattedDate) && <div className="post-meta-info">
          {authors.length > 0 && <div className="post-meta-authors">
              {authors.map(slug => {
    const {name, url, avatarUrl} = resolveAuthor(slug);
    const inner = <>
                    {avatarUrl && <img src={avatarUrl} alt={name} className="post-meta-avatar" />}
                    <span className="post-meta-author-name">{name}</span>
                  </>;
    return url ? <a key={slug} href={url} target="_blank" rel="noopener noreferrer" className="post-meta-author">
                    {inner}
                  </a> : <span key={slug} className="post-meta-author">{inner}</span>;
  })}
            </div>}
          {authors.length > 0 && formattedDate && <span className="post-meta-separator" aria-hidden="true">·</span>}
          {formattedDate && <span className="post-meta-date">{formattedDate}</span>}
        </div>}
      {image && <img src={image} alt="" className="post-meta-image" aria-hidden="true" />}
    </div>;
};

<PostMeta data={{ author: ["dman"], date: "2024-09-19T14:19:39+07:00", image: "/images/posts/how-it-works/using-the-upsun-api/red-background.webp" }} />

## Automate management of your Upsun projects

> Anything you can do, API can do better!

An interesting fact about the Upsun hosting and deployment system, is that all the important actions are done via an API (Abstract Programming Interface) that you also have access to.
The changes you make and the actions that you invoke through the web console can also be triggered programmatically by authenticated HTTP requests.

This means that anything you can do in the Web UI console, you can also automate or trigger remotely!

<Note>
  **Note:**

  Some documentation links may still refer to "Platform.sh", the `platform` CLI tool, and `PLATFORM_*` named environment variables.
  In most cases, you can imagine that the `upsun` CLI tool acts identically to the `platform` CLI tool, so you may read the docs as if they are interchangeable.
</Note>

## The CLI is mostly an API wrapper

We provide the [`upsun` CLI](https://docs.upsun.com/administration/cli.html) to make this easier ( not least because the authentication stuff is annoying to do by hand ) but all that usually does is make an API request on your behalf.

You can see that in action by using `UPSUN_CLI_DEBUG` (a flag that makes the `upsun` CLI tool more verbose). That will log the actual request being made to the API.

```bash {filename="Terminal"} theme={null}
export UPSUN_CLI_DEBUG=1
upsun project:info
```

```{filename="Logs"} theme={null}
Selected project: Client test Upsun (y3fni4nqxhyfa)
> Making HTTP request #1: GET /api/projects/y3fni4nqxhyfa HTTP/1.1
> Host: api.upsun.com
```

Actions and edits are triggered in the same way - via POST.

```bash {filename="Terminal"} theme={null}
upsun environment:pause --environment=feature-ZD12345
```

```{filename="Logs"} theme={null}
...
Making HTTP request #1: POST /api/projects/i4nqxhyy3fnfa/environments/feature-ZD12345/pause HTTP/1.1
> Host: api.upsun.com
...
< Received response for #1 after 1378 ms: HTTP/1.1 200 OK
```

The full API is open and documented for inspection and experimentation at [api.upsun.com](https://api.upsun.com/docs/).
This makes it possible for you to do anything to your project - even create, branch, or change resource allocations - from your own pipelines.

## API requests are authenticated

The [authentication that is used for API access](https://api.upsun.com/docs/#section/Authentication) controls what you can do based on the projects and permissions that are assigned to your user account.

> Note that it is recommended to [create a "machine user" with its own token](https://docs.upsun.com/administration/cli/api-tokens.html#1-create-a-machine-user) if you are intending to delegate tasks to an environment where the token or keys may be shared or visible to others.

* When you use **the web console**, a temporary certificate has been given to your browser when you authenticated -
  usually when you went through `auth.upsun.com` to do your login. This allows the web console in your browser to talk directly to `api.upsun.com` for you.
* When you use **the CLI**, it may require you to "Log in via a browser" window in the same way.
  and a temporary certificate becomes available to your shell environment once you are "Successfully logged in".
* You can also avoid logging in each time you use the CLI by [authenticating using an API token](https://docs.upsun.com/administration/cli/api-tokens.html)
  This is more convenient if you use the CLI a lot.
  * To create an API token, go to the "API Tokens" section of the "Account Settings" tab [on the Console](https://console.upsun.com/), and make that available as a variable named `UPSUN_API_TOKEN` in your shell environment.
* For making requests directly via **the API**, or **for automation and delegation of tasks**, you would also use an API token in this same way.
  * To use the token, the `UPSUN_API_TOKEN`  variable must be set in the environment for the CLI, or passed explicitly in an API request header.
  * You can experiment with semi-raw API requests but still use the CLI to manage authentication via the `upsun api:curl` command.
    For inline documentation on `api:curl` enter `upsun help api:curl` in your terminal.

## Ways of interacting with the API

It's possible to make raw http requests directly to the API endpoint, but it's usually better to use a wrapper of some sort.

### Use `upsun project:curl`

The CLI has an embedded utility that provides direct access to the http requests, and handles the project selection and authentication for you.
See `upsun help project:curl`

```bash {filename="Terminal"} theme={null}
upsun project:curl /environments
```

^ Lists the available environments ([API ref](https://api.upsun.com/docs/#tag/Environment/operation/list-projects-environments)) . Equivalent to `platform environment:list`, but the JSON response may be more useful for automation.

<Note>
  `project:curl` is a shortcut for `api:curl` that pre-selects the project for you, and is easier to use for normal operations.
  They both really are just very thin wrappers around [the documented endpoints](https://api.upsun.com/docs/#section/Introduction/Using-the-REST-API) that format the `curl` command options for you.
</Note>

### Use `curl` directly

```bash {filename="Terminal"} theme={null}
export UPSUN_API_URL=https://api.upsun.com
export UPSUN_PROJECT=ywxgbkce4rmdp
export UPSUN_BRANCH=master
export UPSUN_TOKEN=$(upsun auth:token)

curl -s -H "Authorization: Bearer ${UPSUN_TOKEN}" "${UPSUN_API_URL}/projects/${UPSUN_PROJECT}/environments/${UPSUN_ENVIRONMENT}" \
  | jq "del(.[]._links)"
```

```json {filename="Logs"} theme={null}
[
  {
    "id": "master",
    "_embedded": {
      "deployments": [
        {
          "id": "local",
          "type": "local",
          "name": "local",
          "hosts": null,
          "use_dedicated_grid": false,
          "storage_type": null
        }
      ]
    },
    "created_at": "2024-08-20T10:16:27.324395+00:00",
    "updated_at": "2024-08-20T10:20:49.806440+00:00",
    "name": "master",
    "machine_name": "master-7rqtwti",
    "title": "Master",
    "attributes": {},
    "type": "production",
    "parent": null,
    "status": "active",
    "http_access": {
      "is_enabled": true,
      "addresses": [],
      "basic_auth": {}
    },
    "enable_smtp": true,
    "restrict_robots": true,
    "edge_hostname": "master-7rqtwti-ywxgbkce4rmdp.au.platformsh.site",
    "deployment_state": {
      "last_deployment_successful": true,
      "last_deployment_at": "2024-08-20T10:20:49.805910+00:00",
      "crons": {
        "enabled": true,
        "status": "running"
      }
    },
    "resources_overrides": {},
    "last_active_at": "2024-09-20T03:42:58.347107+00:00",
    "last_backup_at": "2024-09-19T04:11:29.560749+00:00",
    "project": "ywxgbkce4rmdp",
    "is_main": true,
    "is_dirty": false,
    "has_code": true,
    "head_commit": "b1620160b763d1d2314af935d3c0cd23b8a141dc",
    "merge_info": {
      "commits_ahead": 0,
      "commits_behind": 0,
      "parent_ref": null
    },
    "has_deployment": true
  }
]
```

### Use `postman`

The [API support documentation](https://api.upsun.com/docs/#section/Introduction/Using-the-REST-API) also provides an OpenAPI specification which can be imported into tools like Postman for inspection and testing.

* [Install the Postman API explorer](https://www.postman.com/downloads/)
* "Import" the API schema from `https://api.upsun.com/docs/openapispec-platformsh.json`
* Update the "Variables" to set the `baseUrl` to `{{schemes}}://api.upsun.com`
* Update the "Authorization" section to set "Auth Type" type "Bearer Token"
* Generate a token with `upsun auth:token` and paste that into the "Token" field
* Test a request by running the simple "GET" "me" operation

## Use automation to manage your project

With access to this toolset now, you may be able to see some possibilities for management.

* As Upsun resources are charged for pro-rata (usage based), you could cut the RAM and CPU costs for all your preview environments in half by automating a `cron` task them to "pause" every night and weekend.
* You can upscale and downscale the resources in realtime to match demand and traffic on the website.

As an example, you can use [scalsun](https://github.com/upsun/scalsun) to [automatically upscale Upsun resources](/posts/how-tos/configuring-an-autoscaler).
