NAV Navbar

Introduction

Welcome to the Steady API!

You can use our REST-API to fetch data in the scope of your publication. Our API is designed following the JSON API specification.

We implement the OAuth 2.0 authorization framework so that you can implement authentication and authorization for users in your application.

You can view code examples in the dark area to the right, and see example response data for each request.

Our API is only accessible via HTTPS. Enjoy coding!

OAuth 2.0

Create your app

Before you can begin the OAuth process, you must first register a new app with Steady. You can do this in your Steady backend for the project (OWN PROJECTS -> PROJECT -> INTEGRATE -> API).

Client ID and Client Secret

Once your application is registered, Steady will issue “client credentials” in the form of a client identifier and a client secret. The Client ID is a publicly exposed string that is used by the Steady API to identify your application, and is also used by you to build authorization URLs that are presented to users in your application. The Client Secret is used to authenticate the identity of your application when your application requests to access a user’s account, and must be kept private between your application and the API.

Authorization Grant

The first steps in the OAuth 2.0 flow are about obtaining an authorization grant and access token for a user.

Grant Type: Implicit

We don’t offer this flow for clients which cannot use a client secret (e.g. Single Page Apps). Please use Authorization Code grant without client secret for better security.

Grant Type: Authorization Code

The authorization code grant type is the most commonly used because it is optimized for server-side applications, where source code is not publicly exposed, and the client secret can be maintained confidentiality. This is a redirection-based flow, which means that the application must be capable of interacting with the user-agent (i.e. the user’s web browser) and receiving API authorization codes that are routed through the user-agent.

Authorization Code Flow

  https://steadyhq.com/oauth/authorize?
    response_type=code&
    client_id=CLIENT_ID&
    redirect_uri=REDIRECT_URI&
    scope=read&
    state=RANDOM_STRING

Create an authorization link, which sends your user to Steady:

https://steadyhq.com/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=read&state=RANDOM_STRING

Parameter Value
response_type code specifies that your application is requesting an authorization code grant
client_id the CLIENT_ID can be found in the Steady Backend
redirect_uri the REDIRECT_URI you have set in the Steady Backend. After authorization Steady will redirect the user-agent to this URI.
scope read specifies the level of access your application is requesting
state a RANDOM_STRING generated by your application, which you’ll verify later

Step 2: User authorizes your application at Steady

When the user clicks the link, they must first log in to Steady, to authenticate their identity (unless they are already logged in). When the scope is set to read the user is authorized automatically in order to achieve a smooth user experience. Otherwise the user will be prompted by Steady to authorize or deny your application access to their account. Here is an example authorize application prompt:

Step 3: Your application receives an authorization code

  https://your-website.com/oauth/callback?
    code=AUTHORIZATION_CODE&
    state=RANDOM_STRING

If the user gives the authorization, Steady redirects the user-agent to your application redirect URI, which was specified during the client registration, along with an authorization code. The redirect would look something like this:

https://your-website.com/oauth/callback?code=AUTHORIZATION_CODE&state=RANDOM_STRING

Parameter Value
code authorization code you use to request an access token
state the same state value you passed in before

Step 4: Your application requests the access token

POST /api/v1/oauth/token HTTP/1.1
Accept: application/json
Host: steadyhq.com
{
  "client_id": CLIENT_ID,
  "client_secret": CLIENT_SECRET,
  "grant_type": "authorization_code",
  "code": AUTHORIZATION_CODE,
  "redirect_uri": REDIRECT_URI
}

The application requests an access token from the Steady API, by passing the authorization code along with authentication details, including the client secret, to the API token endpoint.

https://steadyhq.com/api/v1/oauth/token

Parameter Value
client_id the CLIENT_ID can be found in the Steady Backend
client_secret the CLIENT_SECRET can be found in the Steady Backend. Optional.
grant_type authorization_code specifies that this request is within an Authorization Code grant flow
code the AUTHORIZATION_CODE received in Step 3
redirect_uri the REDIRECT_URI you have set in the Steady Backend

Step 5: Your application receives the access token

HTTP/1.1 201 CREATED
Content-Type: application/json; charset=utf-8
{
  "access_token": "V1JvWWVXdHcxajkzK1FBdDRwSS95UT09",
  "refresh_token": "MXpyNWRJRUdaMHg0aW9MM2ZJb1lVQT09"
  "token_type": "bearer",
  "expires_in": 604800,
  "scope": "read",
  "info": {
    "id": "5e7607b0-1458-41e4-b6bc-e6301c39e7da",
    "first-name": "Jane",
    "last-name": "Doe",
    "email": "jane.doe@example.com"
  }
}

If the authorization request from Step 4 is valid, Steady will send a response containing the access token.

Parameter Value
access_token the access token issued by Steady
refresh_token the refresh token issued by Steady / null
token_type the type of the token issued (bearer)
expires_in time in seconds until the access token expires
scope specifies the level of access granted
info the basic user information

Refresh the access token

POST /api/v1/oauth/token HTTP/1.1
Accept: application/json
Host: steadyhq.com
{
  "client_id": CLIENT_ID,
  "client_secret": CLIENT_SECRET,
  "grant_type": "refresh_token",
  "refresh_token": REFRESH_TOKEN,
  "redirect_uri": REDIRECT_URI
}

If a refresh token was issued, it may be used to request new access tokens if the original token has expired. Steady only issues a refresh token if you send the client secret along in Step 4. Make your request to refresh the access token to this endpoint:

https://steadyhq.com/api/v1/oauth/token

Parameter Value
client_id the CLIENT_ID can be found in the Steady Backend
client_secret the CLIENT_SECRET can be found in the Steady Backend.
grant_type refresh_token
refresh_token the REFRESH_TOKEN received in Step 5
redirect_uri the REDIRECT_URI you have set in the Steady Backend
  https://steadyhq.com/your_campaign_page?
    oauth_client_id=CLIENT_ID

If you use the following link to send your users to your Steady campaign page - and they complete the subscription - the user is authorized automatically and the flow will continue with Step 3.

https://steadyhq.com/your_campaign_page?oauth_client_id=CLIENT_ID

Parameter Value
oauth_client_id the CLIENT_ID can be found in the Steady Backend

Authorization

To authorize, add “Authorization” as request header field.

GET /api/v1/users/me HTTP/1.1
Accept: application/vnd.api+json
Authorization: Bearer OAUTH2_ACCESS_TOKEN
Host: steadyhq.com

Make sure to replace OAUTH2_ACCESS_TOKEN with the access token of the user you make the request for.

Steady relies on bearer tokens in the “Authorization” request header field.

Authorization: Bearer OAUTH2_ACCESS_TOKEN

Current user

GET /api/v1/users/me HTTP/1.1
Accept: application/vnd.api+json
Authorization: Bearer OAUTH2_ACCESS_TOKEN
Host: steadyhq.com
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json; charset=utf-8
{
  "data": {
    "type": "user",
    "id": "5e7607b0-1458-41e4-b6bc-e6301c39e7da",
    "attributes": {
      "first-name": "Jane",
      "last-name": "Doe",
      "email": "jane.doe@example.com",
      "has-password": true
    }
  }
}

GET https://steadyhq.com/api/v1/users/me

Returns the current basic user data for the user associated with the access token.

Needed scope of access_token:

read

Attributes

Attribute Description
first-name first name of the user
last-name last name of the user
email email address of the user
has-password boolean if the user has set a password for her account

Current subscription

GET /api/v1/subscriptions/me HTTP/1.1
Accept: application/vnd.api+json
Authorization: Bearer OAUTH2_ACCESS_TOKEN
Host: steadyhq.com
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json; charset=utf-8
// when the user has a current subscription
{
  "data": {
    "type": "subscription",
    "id": "8ef509c7-b8fe-4a56-a366-fadf030bfc64",
    "attributes": {
      "state": "not_renewing",
      "period": "annual"
      "currency": "EUR",
      "monthly-amount-in-cents": 1000,
      "inserted-at": "2017-04-08T10:55:31.000000Z",
      "updated-at": "2017-05-01T10:55:31.000000Z",
      "cancelled-at": "2017-05-01T22:00:14.000000Z",
      "trial-ends-at": "2017-05-08T10:55:31.000000Z",
      "active-from": null,
      "expires-at": "2017-05-18T10:55:31.000000Z",
      "rss-feed-url": "https://steadyhq.com/rss/your-publication?auth=6d58b391-156a-4e88-93ff-3fe773f4394d"
    },
    "relationships": {
      "plan": {
        "data": {
          "type": "plan",
          "id": "00083e16-668b-4bc4-8669-927daa408a1c"
        }
      },
      "subscriber": {
        "data": {
          "type": "user",
          "id": "ffc41bfd-871b-4376-8e02-8729c752b2af"
        }
      }
    }
  },
  "included": [{
    "type": "plan",
    "id": "b9d7574f-5246-4c94-ade5-1d4e9b169afc",
    "attributes": {
      "state" : "published",
      "name": "Gold plan",
      "monthly-amount-in-cents" : 2000,
      "annual-amount-in-cents" : 12000,
      "currency" : "EUR",
      "benefits" : "foo bar baz",
      "ask-for-shiping-address" : false,
      "goal-enabled" : false,
      "subscriptions-goal" : nil,
      "countdown-enabled" : false,
      "countdown-ends-at" : nil,
      "hidden" : false,
      "image-url": "https://steady.imgix.net/gfx/steady_logo.svg"
      "inserted-at" : "2018-08-16T09:15:29.803825Z",
      "updated-at" : "2018-08-16T09:15:29.803830Z"
    }
  }]
}

// when the user has no current subscription
{
  "data": null
}

GET https://steadyhq.com/api/v1/subscriptions/me

Returns infos about the current subscription for the user associated with the access token. If the user has no subscription, or it has expired, the data attribute of the response is null.

Needed scope of access_token:

read

Subscription attributes

Attribute Description
state guest / in_trial / active / not_renewing
period monthly / annual — the period of the contract of the user
currency EUR / USD
monthly-amount-in-cents monthly amount of the associated plan (users don’t pay in states in_trial and guest)
inserted-at datetime of the creation of the subscription
updated-at datetime when the subscription was updated the last time on our system
cancelled-at datetime of the cancellation / null
trial-ends-at datetime when the subscription’s trial period will end or has ended / null
active-from datetime when the subscription was paid for the first time/ null
expires-at datetime when the subscription will expire / null
rss-feed-url if you use our podcast features, this is the rss-feed url with authentication for the subscriber

Plan attributes

Attribute Description
state published / archived
name name of the plan
monthly-amount-in-cents the amount a user with a monthly contract has to pay per month
annual-amount-in-cents the amount a user with an annual contract has to pay per year
currency EUR / USD
benefits the benefits of this plan / null
ask-for-shipping-address boolean if we ask the user for her shipping address after she subscribed
goal-enabled boolean if this plan has a goal of a certain amount of subscriptions
subscriptions-goal integer how many subscription should be reached if goal is enabled / null
countdown-enabled boolean if a countdown for this plan is enabled
countdown-ends-at datetime when the countdown will end if it is enabled / null
hidden boolean if the plan is hidden
image-url plan image url / null
inserted-at datetime of the creation of the plan
updated-at datetime when the plan was updated the last time on our system

REST

The following endpoints are all REST based. You can find your Api-Key in your Steady Backend.

Publication

GET /publication

GET /api/v1/publication HTTP/1.1
Accept: application/vnd.api+json
Authorization: X-Api-Key YOUR_API_KEY
Host: steadyhq.com
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json; charset=utf-8
{
  "data": {
    "type": "publication",
    "id": "0879c0a7-cc51-44fc-ac35-4bec65735d5b",
    "attributes": {
      "title": "Title of your publication",
      "campaign-page-url" : "https://steadyhq.com/your-publication",
      "members-count": 10,
      "paying-members-count": 7,
      "trial-members-count": 2,
      "guest-members-count": 1,
      "monthly-amount-in-cents": 14223,
      "editor-name": "Foo Bear",
      "trial-period-activated": true,
      "public": true,
      "js-widget-url": "https://steadyhq.com/widget_loader/0879c0a7-cc51-44fc-ac35-4bec65735d5b",
      "inserted-at" : "2018-08-16T09:15:29.803825Z",
      "updated-at" : "2018-08-16T09:15:29.803830Z"
    }
  }
}

GET https://steadyhq.com/api/v1/publication

Returns infos about the publication associated with the Api-Key.

Attributes

See our FAQ for further explanations.

Attribute Description
title the title of the publication
campaign-page-url the url of your steady page
members-count the members count of the publication
paying-members-count the count of paying members of the publication
trial-members-count the count of trial members of the publication
guest-members-count the count of guest members of the publication
monthly-amount-in-cents the sum of the membership fees, the publication earns in a month
editor-name the name of the publisher as shown on the Steady Page
trial-period-activated boolean if trial memberships are enabled for the publication
public boolean if the publication has been made public
js-widget-url the url of the JS-Steady-Plugin of your publication
inserted-at datetime of the creation of the publication
updated-at datetime when the publication was updated the last time on our system

Plans

GET /plans

GET /api/v1/plans HTTP/1.1
Accept: application/vnd.api+json
Authorization: X-Api-Key YOUR_API_KEY
Host: steadyhq.com
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json; charset=utf-8
{
  "data": [
    {
      "type": "plan",
      "id": "b9d7574f-5246-4c94-ade5-1d4e9b169afc",
      "attributes": {
        "state" : "published",
        "name": "Gold plan",
        "monthly-amount-in-cents" : 2000,
        "annual-amount-in-cents" : 12000,
        "currency" : "EUR",
        "benefits" : "foo bar baz",
        "ask-for-shiping-address" : false,
        "goal-enabled" : false,
        "subscriptions-goal" : nil,
        "countdown-enabled" : false,
        "countdown-ends-at" : nil,
        "hidden" : false,
        "image-url": "https://steady.imgix.net/gfx/steady_logo.svg"
        "inserted-at" : "2018-08-16T09:15:29.803825Z",
        "updated-at" : "2018-08-16T09:15:29.803830Z"
      }
    },
    ...
  ]
}

GET https://steadyhq.com/api/v1/plans

Returns an array with all plans of the publication.

Attributes

Attribute Description
state draft / published / archived
name name of the plan
monthly-amount-in-cents the amount a user with a monthly contract has to pay per month
annual-amount-in-cents the amount a user with an annual contract has to pay per year
currency EUR / USD
benefits the benefits of this plan / null
ask-for-shipping-address boolean if we ask the user for her shipping address after she subscribed
goal-enabled boolean if this plan has a goal of a certain amount of subscriptions
subscriptions-goal integer how many subscription should be reached if goal is enabled / null
countdown-enabled boolean if a countdown for this plan is enabled
countdown-ends-at datetime when the countdown will end if it is enabled / null
hidden boolean if the plan is hidden
image-url plan image url / null
inserted-at datetime of the creation of the plan
updated-at datetime when the plan was updated the last time on our system

Subscriptions

GET /subscriptions

GET /api/v1/subscriptions HTTP/1.1
Accept: application/vnd.api+json
Authorization: X-Api-Key YOUR_API_KEY
Host: steadyhq.com
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json; charset=utf-8
{
  "data": [
    {
      "type": "subscription",
      "id": "8ef509c7-b8fe-4a56-a366-fadf030bfc64",
      "attributes": {
        "state": "not_renewing",
        "period": "annual"
        "currency": "EUR",
        "monthly-amount-in-cents": 1000,
        "inserted-at": "2017-04-08T10:55:31.000000Z",
        "updated-at": "2017-05-01T10:55:31.000000Z",
        "cancelled-at": "2017-05-01T22:00:14.000000Z",
        "trial-ends-at": "2017-05-08T10:55:31.000000Z",
        "active-from": null,
        "expires-at": "2017-05-18T10:55:31.000000Z",
        "rss-feed-url": "https://steadyhq.com/rss/your-publication?auth=6d58b391-156a-4e88-93ff-3fe773f4394d"
      },
      "relationships": {
        "plan": {
          "data": {
            "type": "plan",
            "id": "00083e16-668b-4bc4-8669-927daa408a1c"
          }
        },
        "subscriber": {
          "data": {
            "type": "user",
            "id": "ffc41bfd-871b-4376-8e02-8729c752b2af"
          }
        }
      }
    },
    "included": [{
      "type": "plan",
      "id": "b9d7574f-5246-4c94-ade5-1d4e9b169afc",
      "attributes": {
        "state" : "published",
        "name": "Gold plan",
        "monthly-amount-in-cents" : 2000,
        "annual-amount-in-cents" : 12000,
        "currency" : "EUR",
        "benefits" : "foo bar baz",
        "ask-for-shiping-address" : false,
        "goal-enabled" : false,
        "subscriptions-goal" : nil,
        "countdown-enabled" : false,
        "countdown-ends-at" : nil,
        "hidden" : false,
        "image-url": "https://steady.imgix.net/gfx/steady_logo.svg"
        "inserted-at" : "2018-08-16T09:15:29.803825Z",
        "updated-at" : "2018-08-16T09:15:29.803830Z"
      }
    }],
    ...
  ]
}

GET https://steadyhq.com/api/v1/subscriptions

Returns an array with all current subscriptions of the publication.

Attributes

Attribute Description
state guest / in_trial / active / not_renewing
period monthly / annual — the period of the contract of the user
currency EUR / USD
monthly-amount-in-cents monthly amount of the associated plan (users don’t pay in states in_trial and guest)
inserted-at datetime of the creation of the subscription
updated-at datetime when the subscription was updated the last time on our system
cancelled-at datetime of the cancellation / null
trial-ends-at datetime when the subscription’s trial period will end or has ended / null
active-from datetime when the subscription was paid for the first time/ null
expires-at datetime when the subscription will expire / null
rss-feed-url if you use our podcast features, this is the rss-feed url with authentication for the subscriber

POST /subscriptions/:subscription_id/cancel

POST /api/v1/subscriptions/8ef509c7-b8fe-4a56-a366-fadf030bfc64/cancel HTTP/1.1
Accept: application/vnd.api+json
Authorization: X-Api-Key YOUR_API_KEY
Host: steadyhq.com
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json; charset=utf-8
{
  "data": {
    "type": "subscription",
    "id": "8ef509c7-b8fe-4a56-a366-fadf030bfc64",
    "attributes": {
      "state": "not_renewing",
      "period": "annual"
      "currency": "EUR",
      "monthly-amount-in-cents": 1000,
      "inserted-at": "2017-04-08T10:55:31.000000Z",
      "updated-at": "2017-05-01T10:55:31.000000Z",
      "cancelled-at": "2017-05-01T22:00:14.000000Z",
      "trial-ends-at": "2017-05-08T10:55:31.000000Z",
      "active-from": null,
      "expires-at": "2017-05-18T10:55:31.000000Z",
      "rss-feed-url": "https://steadyhq.com/rss/your-publication?auth=6d58b391-156a-4e88-93ff-3fe773f4394d"
    },
    "relationships": {
      "plan": {
        "data": {
          "type": "plan",
          "id": "00083e16-668b-4bc4-8669-927daa408a1c"
        }
      },
      "subscriber": {
        "data": {
          "type": "user",
          "id": "ffc41bfd-871b-4376-8e02-8729c752b2af"
        }
      }
    },
    "included": [{
      "type": "plan",
      "id": "b9d7574f-5246-4c94-ade5-1d4e9b169afc",
      "attributes": {
        "state" : "published",
        "name": "Gold plan",
        "monthly-amount-in-cents" : 2000,
        "annual-amount-in-cents" : 12000,
        "currency" : "EUR",
        "benefits" : "foo bar baz",
        "ask-for-shiping-address" : false,
        "goal-enabled" : false,
        "subscriptions-goal" : nil,
        "countdown-enabled" : false,
        "countdown-ends-at" : nil,
        "hidden" : false,
        "image-url": "https://steady.imgix.net/gfx/steady_logo.svg"
        "inserted-at" : "2018-08-16T09:15:29.803825Z",
        "updated-at" : "2018-08-16T09:15:29.803830Z"
      }
    }]
  }
}

POST https://steadyhq.com/api/v1/subscriptions/:subscription_id/cancel

Cancels a subscription respecting the end of the current term.

In case the subscription can’t be canceled (e.g. because it already is cancelled), a response with status code 422 will be returned.

Attributes

Attribute Description
state not_renewing
period monthly / annual — the period of the contract of the user
currency EUR / USD
monthly-amount-in-cents monthly amount of the associated plan (users don’t pay in states in_trial and guest)
inserted-at datetime of the creation of the subscription
updated-at datetime when the subscription was updated the last time on our system
cancelled-at datetime of the cancellation / null
trial-ends-at datetime when the subscription’s trial period will end or has ended / null
active-from datetime when the subscription was paid for the first time/ null
expires-at datetime when the subscription will expire / null
rss-feed-url if you use our podcast features, this is the rss-feed url with authentication for the subscriber