Skip to Content
DocsReferencePrivate API

Stellate Private API

🚫

This API is not intended for public consumption.

We share this documentation with you to allow you to better integrate with Stellate systems. However, this API is not meant for wider consumption and we ask that you do not share this documentation outside of your team.

The API is avialable at https://api.stellate.co/api.

For authorization, you will need to provide a valid Access Token via the stellate-token header. You can create new tokens on your Dashboard at https://stellate.co/app/settings/access-tokens.

⚠️

Those access tokens are scoped to your user, not a specific organization. Any request using one of your tokens will have the same permissions you have, including access to all organizations and services you have on Stellate.

List all organizations for a user

This function will fetch all organizations relating to a user token, we will use this to write our service to a specific organization.

list-organizations.ts
const token = '<your-token>'
const apiUrl = 'https://api.stellate.co/api'
 
async function listOrganizations() {
  const response = await fetch(apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'graphcdn-token': token,
    },
    body: JSON.stringify({
      query: /* GraphQL */ `
        query {
          user {
            organizations {
              id
              name
              slug
            }
          }
        }
      `,
    }),
  })
 
  const result = await response.json()
  return result.data.user.organizations
}

List all services for a specific organization

list-services.ts
async function listServices(slug) {
  const response = await fetch(apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'graphcdn-token': token,
    },
    body: JSON.stringify({
      query: /* GraphQL */ `
        query ($slug: String!) {
          organization(slug: $slug) {
            name
            services(first: 10) {
              edges {
                node {
                  id
                  name
                  ## This config.input is the raw config we have written to
                  ## our GraphQL API, used to e.g. reproduce the raw YAML
                  ## configuration file
                  config {
                    input
                  }
                }
              }
            }
          }
        }
      `,
      variables: { slug },
    }),
  })
 
  const result = await response.json()
  return result.data.organization.apps
}

Service configuration

See Configuration File for more information on each of the configuration items.

config.ts
const backendURL = '<your_backend_url>'
 
const config = {
  // The name to give to our service in stellate. This needs to be unique,
  // otherwhise you will get an error back
  name: 'node-write-test',
  originUrl: backendURL,
  // You can fill in a schema here to fetch the introspection from
  // or pass in the introspection/schema yourself
  schema: backendUrl,
  ignoreOriginCacheControl: true,
  enablePlayground: true,
  injectHeaders: true,
  headers: {
    'something-to-inject': '1',
  },
  keyFields: {
    types: {
      // If you have types that aren't identified by id or _id
      // you can fill them in here, this is the key we will use for
      // purging/...
      YourType: ['specialKey'],
    },
  },
  scopes: {
    // Scopes are a way to create separate cache buckets
    // for instance a `query { user }` that is based on
    // the auth-token might be worth scoping.
    // This also makes it so that people can't access others
    // resources as we don't perform the authorization logic
    // your back-end does
    AUTHENTICATED: 'header:Authorization',
  },
  // If you have any alternative typenames like query refers to RootQuery fill them in here
  rootTypeNames: { query: 'Query', mutation: 'Mutaiton' },
  rules: [
    {
      description: 'Cache all queries',
      maxAge: 600,
      swr: 900,
      types: ['Query'],
    },
    {
      description: 'Put users in a separate bucket',
      maxAge: 600,
      swr: 900,
      scope: 'AUTHENTICATED',
      types: ['User'],
    },
  ],
  // When we see these headers we will automatically bypass the cache for you
  // this can come in handy for preview-urls, ...
  bypassCacheHeaders: [{ name: 'x-preview-token' }],
}

Some API calls require schema information. You can either provide a local schema you have available, or fetch it via Introspection.

introspection.ts
import fetch from 'node-fetch'
import { getIntrospectionQuery } from 'graphql'
 
const backendURL = 'https://trygql.formidable.dev/graphql/basic-pokedex'
 
const introspectionResponse = await fetch(originUrl, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    query: introspectionQuery,
  }),
})
 
const { data: schema } = await introspectionResponse.json()

Create a new service

This method is used to create a new service in a given organization (identified via the orgId parameter).

create-service.ts
const token = '';
const apiUrl = 'https://api.stellate.co/api'
const schema = ''
 
// See above for more information about the `config` variable
const config = { ... }
 
async function createApp(orgId, schema) {
  const result = await fetch(apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'graphcdn-token': token,
    },
    body: JSON.stringify({
      query: /* GraphQL */ `
        mutation (
          $input: Input!
          $schema: IntrospectionQuery
          $organizationId: String!
        ) {
          createAppCli(
            input: $input
            schema: $schema
            organizationId: $organizationId
          ) {
            id
            config {
              input
            }
          }
        }
      `,
      variables: {
        input: config,
        schema: schema,
        organizationId: orgId
      }
    })
  })
 
  return await result.json()
}

Update an existing service

This method is used to update the configuration of an existing service

update-service.ts
const token = '';
const apiUrl = 'https://api.stellate.co/api'
const schema = ''
// See above for more information about the `config` variable
const config = { ... }
 
async function pushAppConfig(schema) {
  const result = await fetch(apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'graphcdn-token': token,
    },
    body: JSON.stringify({
      query: /* GraphQL */ `
        mutation (
          $input: Input!
          $appName: String!
          $schema: IntrospectionQuery
        ) {
          pushAppConfig(
            input: $input
            appName: $appName
            schema: $schema
            ## this will confirm before any configuration items is deleted
            allowDeletion: true
          )
        }
      `,
      variables: {
        input: config,
        schema: schema,
        appName: config.name,
      }
    })
  })
}

Delete a service

To delete an existing service, use the following mutation.

delete-service.ts
const token = ''
const apiUrl = 'https://api.stellate.co/api'
 
async function deleteApp() {
  const result = await fetch(apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'graphcdn-token': token,
    },
    body: JSON.stringify({
      query: /* GraphQL */ `
        mutation ($appName: ServiceName) {
          deleteApp(name: $appName)
        }
      `,
      variables: {
        appName: config.name,
      },
    }),
  })
}

Add a custom domain to an existing service

To add a custom domain to an existing service, make sure the DNS records are provisioned and point at ecp.map.fastly.net. Once DNS is properly configured, use the following mutation.

add-custom-domain.ts
const token = ''
const apiUrl = 'https://api.stellate.co/api'
 
async function deleteApp() {
  const result = await fetch(apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'graphcdn-token': token,
    },
    body: JSON.stringify({
      query: /* GraphQL */ `
        mutation ($appName: ServiceName!, $domain: String!) {
          addCustomDomain(appName: $serviceName, domain: $domain) {
            id
            customDomain
            isCustomDomainVerified
            customDomainCnameValidation
            customDomainStatus
            customDomainError
          }
        }
      `,
      variables: {
        appName: config.name,
        domain: domain,
      },
    }),
  })
}
Last updated on