# Publish Schemas to GraphOS using the Platform API

This guide covers how to publish schemas using the [Platform API](https://www.apollographql.com/docs/graphos/reference/platform-api/). Consult the [Rover guide](https://www.apollographql.com/docs/graphos/platform/schema-management/delivery/publishing/rover) to learn how to use the Rover CLI for publication.

Apollo recommends using the Rover CLI for most schema publishing.
The Platform API is best for advanced use cases like custom CI/CD integration or publishing multiple subgraphs simultaneously.

## Prerequisites

1. [A subgraph or graph API key from GraphOS Studio](https://studio.apollographql.com/org/settings/api-keys).
2. Familiarity with invoking APIs during CI/CD processes.

## Publish subgraph schemas

When working with supergraphs and the Platform API, you can either individually publish each subgraph's schema to GraphOS, or publish multiple subgraphs simultaneously.

Regardless of which approach you choose you need to:

1. Identify the name of the subgraph you're publishing to. You can view the names of your existing subgraphs from your variant's **Subgraphs** page in [GraphOS Studio](https://studio.apollographql.com/?referrer=docs-content).

2. If you're publishing a subgraph for the first time, also obtain the **routing URL** of that subgraph. This is the URL that your router will use to communicate with the subgraph.

   * If GraphOS already knows your subgraph's routing URL, you don't need to provide this value unless you're changing it.

3. Use one of the following mutations, depending on whether you're publishing a [single subgraph](https://www.apollographql.com/docs/graphos/platform/schema-management/delivery/publishing/platform-api.md#publish-a-single-subgraph) or [multiple subgraphs](https://www.apollographql.com/docs/graphos/platform/schema-management/delivery/publishing/platform-api.md#publish-multiple-subgraphs).

### Subgraph inputs for the Platform API

Subgraph inputs are the same for both single and multiple subgraph publishes.
Single publishes use arguments directly on the mutation. Multiple subgraph publishes put inputs in an array within the arguments of the mutation.

These are the minimum required fields for each subgraph input:

* `name`: The name of the subgraph. This is the name that will be used to identify the subgraph in GraphOS.
* `activePartialSchema.sdl`: The schema that will be used to compose the supergraph. This is a string that contains the SDL of the schema.
* `url`: The URL of the subgraph. This is the URL that will be used to route requests to the subgraph.

An example subgraph input looks like this:

```json
{
  "name": "test-subgraph",
  "activePartialSchema": {
    "sdl": "type Query {\n    hello: World\n}\n\ntype World {\n    id: ID!  \n}"
  },
  "url": "http://localhost:6499",    
}
```

### Publish a single subgraph

To publish a single subgraph, use the following mutation with the appropriate variables:

```graphql
mutation PublishSubgraphSchema($graphId: ID!, $variantName: String!, $subgraphName: String!, $schemaDocument: PartialSchemaInput!, $url: String) {
  graph(id: $graphId) {
    publishSubgraph(graphVariant: $variantName, activePartialSchema: $schemaDocument, name: $subgraphName, url: $url, revision: "") { 
      launchUrl
      updatedGateway
      wasCreated
    }
  }
}
```

```json title=Variables
{
  "graphId": "<graph-id>",
  "variantName": "<variant-name>",
  "subgraphName": "<subgraph-name>",
  "schemaDocument": {
    "sdl": "<subgraph-sdl>"
  },
  "url": "<routing-url>",    
}
```

#### Example variables for publishing a single subgraph

As an example, if you were to publish a subgraph with the name `test-subgraph`, the variables would be:

```json
{
  "graphId": "test-graph",
  "variantName": "dev",
  "subgraphName": "test-subgraph",
  "schemaDocument": {
    "sdl": "type Query {\n    hello: World\n}\n\ntype World {\n    id: ID!  \n}"
  },
  "url": "http://localhost:6499",    
}
```

### Publish multiple subgraphs

To publish multiple subgraphs simultaneously, use the following mutation with the appropriate variables:

```graphql
mutation PublishSubgraphSchemas($graphId: ID!, $variantName: String!, $subgraphInputs: [PublishSubgraphsSubgraphInput!]!) {
  graph(id: $graphId) {
    publishSubgraphs(graphVariant: $variantName, revision: "", subgraphInputs: $subgraphInputs) { 
      launchUrl
      updatedGateway
      wasCreated
    }
  }
}
```

```json title=Variables
{
  "graphId": "my-graph",
  "variantName": "my-variant",
  "subgraphInputs": [
    {
      "name": "locations",
      "activePartialSchema": {
        "sdl": "type Query {\n  location(id: ID!): Location\n}\n\ntype Location {\n  id: ID!\n  name: String\n}"
      },
      "url": "https://flyby-locations-sub.herokuapp.com/"
    },
    {
      "name": "reviews",
      "activePartialSchema": {
        "sdl": "type Query {\n  review(id: ID!): Review\n}\n\ntype Review {\n  id: ID!\n  text: String\n}"
      }, 
      "url": "https://flyby-reviews-sub.herokuapp.com/"
    }
  ]
}
```

#### Example variables for publishing multiple subgraphs

As an example of publishing multiple subgraphs, if you were to publish two subgraphs with the names `test-subgraph` and `test-subgraph-2`, the variables would be:

```json
{
  "graphId": "test-graph",
  "variantName": "dev",
  "subgraphInputs": [
    {
      "name": "test-subgraph",
      "activePartialSchema": {
        "sdl": "type Query {\n    hello: World\n}\n\ntype World {\n    id: ID!  \n}"
      },
      "url": "http://localhost:6499"
    },
    {
      "name": "test-subgraph-2",
      "activePartialSchema": {
        "sdl": "type Query {\n    foo: Bar\n}\n\ntype Bar {\n    baz: String\n}"
      }, 
      "url": "http://localhost:6500"
    }
  ]
}
```

## Publish monograph schemas

For monographs, the publication process is simpler:

1. Prepare your complete schema in SDL format.

2. Use the `graph.uploadSchema` mutation with the following variables.

```graphql
mutation PublishMonographSchema($graphId: ID!, $variantName: String!, $schemaDocument: String) {
  graph(id: $graphId) {
    uploadSchema(tag: $variantName, schemaDocument: $schemaDocument) { 
      code
      message
      success
      publication {
        schema {
          document
          hash
        }
      }
    }
  }
}
```

```json title=Variables
{
  "graphId": "my-graph",
  "variantName": "my-variant",
  "schemaDocument": "type Query {\n  hello: String\n}"
}
```

## Publish with continuous delivery

To get the most out of GraphOS, you should publish each update to any production schema as soon as it occurs. Consequently, schema publishing should be part of your continuous delivery pipeline.

Here's a sample continuous delivery configuration for schema publishing using the Platform API in CircleCI:

```yaml
version: 2

jobs:
  build:
    docker:
      - image: circleci/node:16

    steps:
      - checkout

      - run: npm install
      
      # Start the GraphQL server if needed
      - run:
          name: Starting server
          command: npm start
          background: true

      # Wait for server to start
      - run: sleep 5

      # When running on the 'main' branch, push the latest schema to GraphOS
      - run: |
          if [ "${CIRCLE_BRANCH}" == "main" ]; then
            # This example uses curl to call the Platform API
            curl -X POST \
              -H "Content-Type: application/json" \
              -H "x-api-key: $APOLLO_KEY" \
              -d '{
                "query": "mutation($graphId: ID!, $schemaDocument: String!) { graph(id: $graphId) { uploadSchema(schemaDocument: $schemaDocument, tag: \"current\") { code, message, success } } }",
                "variables": {
                  "graphId": "my-graph",
                  "schemaDocument": "$(cat schema.graphql | sed 's/"/\\"/g' | tr -d '\n')"
                }
              }' \
              https://graphql.api.apollographql.com/api/graphql
          fi
```

## Additional resources

* [Platform API reference](https://www.apollographql.com/docs/graphos/reference/platform-api/)
* [GraphOS CI/CD best practices](https://www.apollographql.com/tutorials/enterprise-managed-federation)
