NAV
shell python javascript

Introduction

Welcome to the steg.ai API! You can use our API to access steg.ai API endpoints, which can protect and authenticate media.

We have code examples in Shell, Python, and JavaScript! You can view it in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.

Base URL:

"https://api.steg.ai"

Authentication

To authorize, include the API key in the header like in this code:

import requests

requests.get("https://api.steg.ai/<ENDPOINT>",
  headers={
    "x-api-key" : "api_key_here"
  },
)
# With shell, you can just pass the correct header with each request
curl "https://api.steg.ai" \
  -H "x-api-key: api_key_here"
fetch(
  "https://api.steg.ai",
  headers: {
    "x-api-key": "api_key_here"
  }
)

Make sure to replace api_key_here with your own API key.

steg.ai uses API keys to allow access to the API. You can register a new steg.ai API key by contacting us.

steg.ai expects for the API key to be included in all API requests to the server in a header that looks like the following:

x-api-key: api_key_here

Response

All steg.ai endpoints will return a successful response in the following format:

Attribute Type Description
message string A message about the response.
data object/array Contains the data to the response. See each section's "Data object" to see what properties it contains.

For non-successful responses, see Errors for more information.

How To Guides

This section describes the most common flows to support developers getting started with the steg.ai API. Each step is linked to their respective section for more information.

How to Encode an Image

In this guide, we'll show the full process on how to encode the following image using python as an example.

The image is called download.png.

01) Generate presigned-url to upload image

See upload api for more information.


import json

import requests

BASE_URL = "https://api.steg.ai"
APIKEY = "API_KEY_HERE"

headers = {
    "Content-Type": "application/json",
    "x-api-key": APIKEY
}
payload = {
    "name": "download.png",
    "content_type": "image/png"
}
response = requests.post(f"{BASE_URL}/upload",
                         headers=headers, data=json.dumps(payload))

# Need these values for next steps
post_to_fields = response.json().get("data").get("post_to")
media_id = response.json().get("data").get("media_id")

02) Upload an image to the url

See upload api for more information.


with open("download.png", "rb") as file:
    url = post_to_fields.get("url")
    form_data = post_to_fields.get("fields")
    files = {
        "file": file
    }

    requests.post(url=url, files=files, data=form_data)

03) Encode the image

See encode api for more information.


payload = {
    "media_id": media_id,
}
response = requests.post(
    f"{BASE_URL}/encode_image_async", headers=headers, data=json.dumps(payload))

request_id = response.json().get("data").get("request_id")

04) Get the status of the encoding

See Check Status API for more information.


while True:
    response = requests.get(
        f"{BASE_URL}/media_status?request_id={request_id}", headers=headers)
    request_data = response.json().get("data")
    if request_data.get("status") == "Completed.":
        media_data = request_data.get("media_data")
        media_url = media_data.get("media_url")
        break

05) Download the encoded image


response = requests.get(media_url)
if response.status_code == 200:
    with open("encoded_image.png", 'wb') as f:
        f.write(response.content)

Full code below


import json

import requests

BASE_URL = "https://api.steg.ai"
APIKEY = "API_KEY_HERE"

headers = {
    "Content-Type": "application/json",
    "x-api-key": APIKEY
}
payload = {
    "name": "download.png",
    "content_type": "image/png"
}
response = requests.post(f"{BASE_URL}/upload",
                         headers=headers, data=json.dumps(payload))

post_to_fields = response.json().get("data").get("post_to")
media_id = response.json().get("data").get("media_id")

with open("download.png", "rb") as file:
    url = post_to_fields.get("url")
    form_data = post_to_fields.get("fields")
    files = {
        "file": file
    }

    requests.post(url=url, files=files, data=form_data)

payload = {
    "media_id": media_id,
}
response = requests.post(
    f"{BASE_URL}/encode_image_async", headers=headers, data=json.dumps(payload))

request_id = response.json().get("data").get("request_id")

while True:
    response = requests.get(
        f"{BASE_URL}/media_status?request_id={request_id}", headers=headers)
    request_data = response.json().get("data")
    if request_data.get("status") == "Completed.":
        media_data = request_data.get("media_data")
        media_url = media_data.get("media_url")

        response = requests.get(url=media_url)
        with open("encoded_image.png", 'wb') as f:
            f.write(response.content)
        break

How to Decode an Image

In this guide, we'll show the full process on how to decode the following image using python as an example.

The image is called watermarked_file.png. When successfully decoded, the image will contain data with the following message: "this is an example image that's been watermarked".

01) Generate presigned-url to upload image

See upload api for more information.


import json
import requests

BASE_URL = "https://api.steg.ai"
APIKEY = "API_KEY_HERE"

headers = {
    "Content-Type": "application/json",
    "x-api-key": APIKEY
}
payload = {
    "name": "watermarked_file.png",
    "content_type": "image/png"
}
response = requests.post(f"{BASE_URL}/upload",
                         headers=headers, data=json.dumps(payload))

# Need these values for next steps
post_to_fields = response.json().get("data").get("post_to")
media_id = response.json().get("data").get("media_id")

02) Upload the image to the url

See upload api for more information.


with open("watermarked_file.png", "rb") as file:
    url = post_to_fields.get("url")
    form_data = post_to_fields.get("fields")
    files = {
        "file": file
    }

    requests.post(url=url, files=files, data=form_data)

03) Decode the image

See Decode API for more information.


payload = {
    "media_id": media_id,
}
response = requests.post(
    f"{BASE_URL}/decode_image_async", headers=headers, data=json.dumps(payload))

request_id = response.json().get("data").get("request_id")

04) Get the data from the image

See check status api for more information.


while True:
    response = requests.get(
        f"{BASE_URL}/media_status?request_id={request_id}", headers=headers)
    request_data = response.json().get("data")
    if request_data.get("status") == "Completed.":
        media_data = request_data.get("media_data")
        print(media_data)
        break

Full code below


import json
import requests

BASE_URL = "https://api.steg.ai"
APIKEY = "API_KEY_HERE"

headers = {
    "Content-Type": "application/json",
    "x-api-key": APIKEY
}
payload = {
    "name": "watermarked_file.png",
    "content_type": "image/png"
}
response = requests.post(f"{BASE_URL}/upload",
                         headers=headers, data=json.dumps(payload))

post_to_fields = response.json().get("data").get("post_to")
media_id = response.json().get("data").get("media_id")

with open("watermarked_file.png", "rb") as file:
    url = post_to_fields.get("url")
    form_data = post_to_fields.get("fields")
    files = {
        "file": file
    }

    requests.post(url=url, files=files, data=form_data)

payload = {
    "media_id": media_id,
}
response = requests.post(
    f"{BASE_URL}/decode_image_async", headers=headers, data=json.dumps(payload))

request_id = response.json().get("data").get("request_id")

while True:
    response = requests.get(
        f"{BASE_URL}/media_status?request_id={request_id}", headers=headers)
    request_data = response.json().get("data")
    if request_data.get("status") == "Completed.":
        media_data = request_data.get("media_data")
        print(media_data)
        break

How to Set Custom Data When Encoding

You might have an usecase where the attributes provided: [license, owner] in the encode api aren't useful or needed. We provide a custom parameter allowing users to put any data they want into their media. The custom object is an object allowing any key-value pairs you can think of.


import json
import requests

BASE_URL = "https://api.steg.ai"
APIKEY = "API_KEY_HERE"

headers = {
    "Content-Type": "application/json",
    "x-api-key": APIKEY
}

payload = {
    "media_id": "example_media_id",
    "custom": {
      "custom_key_1": "custom_value_1",
    }
}
requests.post(
    f"{BASE_URL}/encode_image_async", headers=headers, data=json.dumps(payload))


Example 01: Including location data into the image


import json

import requests

BASE_URL = "https://api.steg.ai"
APIKEY = "API_KEY_HERE"

headers = {
    "Content-Type": "application/json",
    "x-api-key": APIKEY
}

payload = {
    "media_id": "example_media_id",
    "custom": {
      "location": "New York, NY",
      "ip_address": "192.158.1.38"
    }
}
requests.post(
    f"{BASE_URL}/encode_image_async", headers=headers, data=json.dumps(payload))


How To Subscribe To A Webhook Event

In this guide, we’ll show the full process on how to subscribe to our webhooks using python as an example.

Creating webhook subscription


import json
import requests

BASE_URL = "https://api.steg.ai"
APIKEY = "API_KEY_HERE"

headers = {
    "Content-Type": "application/json",
    "x-api-key": APIKEY
}

payload = {
    "event": "encode.success",
    "url": "https://yourdomain.com/custom_endpoint"
}
requests.post(f"{BASE_URL}/webhook", headers=headers, data=json.dumps(payload))

# If you want your URL to handle "decode.success" events too, then another request needs to be made:
payload = {
    "event": "decode.success",
    "url": "https://yourdomain.com/custom_endpoint"
}
requests.post(f"{BASE_URL}/webhook", headers=headers, data=json.dumps(payload))

We’re using Flask as an example of a server to handle the defined URL in the previous step. Make sure you save the secret key in your system. You must return the same header: X-Hook-Secret and status code: 200 as the response.

Full server example code


import base64
import hashlib
import hmac
import json
import os

from flask import Flask, request, jsonify

secret_key = os.getenv("stegai_secret_key")
api_key = os.getenv("stegai_api_key")

app = Flask(__name__)

@app.route('/custom_endpoint', methods=['POST'])
def handle_webhook():
    try:
        # Handle creating the subscription for the first time
        if request.headers.get("X-Hook-Secret"):
            # Save the secret key value in system

            # Creating a JSON response with status code 200 and custom header 'X-Hook-Secret'
            response = jsonify()
            response.status_code = 200

            # X-Hook-Secret must return the same value as the request
            response.headers['X-Hook-Secret'] = request.headers.get("X-Hook-Secret")
            return response

        # Handle incoming webhook events
        elif request.headers.get("X-StegAI-Signature"):

            # Verify the signature
            timestamp_prefixed, signature_hash_prefixed = request.headers.get("X-StegAI-Signature").split(",")

            # Remove `=` from the string
            timestamp = timestamp_prefixed.split('=')[0]
            expected_signature = signature_hash_prefixed.split('=')[0]
            request_data = request.json

            # Calculate the signature
            signature_str = f"{timestamp}.{request_data}".encode('utf-8')

            # This is the actual signature generated using HMAC-SHA256. It uses the secret key to hash the signature_str
            calculated_signature = hmac.new(secret_key.encode('utf-8'), signature_str, hashlib.sha256).hexdigest()

            # Verify the incoming the signature and the signature calculated
            if calculated_signature == expected_signature:
                # Do some action
                # for example downloading the encoded version of the asset
                media_id = request_data.get("media_id")
                headers = {
                    "Content-Type" : "application/json",
                    "x-api-key" : api_key
                }
                response = requests.get("https://api.steg.ai/asset?media_id={media_id}", headers=headers)

            return jsonify(), 200
        return jsonify(), 500

    except Exception as e:
        return jsonify(), 500

if __name__ == '__main__':
    app.run(debug=False, port=5000)

Sample Applications

This section provides examples of sample applications in Python and JavaScript that use steg.ai's API, which encapsulate the entire process of encoding and decoding an image.

Head to the sample apps repo to access the repository and instructions on how to run them.

Encode API

steg.ai offers two asychronous endpoints to encode images or videos.

Encode

POST /encode

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
};
const body = {
    "assets": [
        {
            "media_id": "EXAMPLE_MEDIA_ID"
        },
        {
            "url": "www.path_to_png_image.com",
            "mime_type": "image/png"
        }
    ]
};
fetch("https://api.steg.ai/encode",
    method: "POST",
    headers: headers ,
    body: JSON.stringify(body)
)
import json
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
}
body = {
    "assets": [
        {
            "media_id": "EXAMPLE_MEDIA_ID"
        },
        {
            "url": "www.path_to_png_image.com",
            "mime_type": "image/png"
        }
    ]
}
requests.post("https://api.steg.ai/encode", headers=headers, body=json.dumps(body))
curl --request POST "https://api.steg.ai/encode" \
--header "Content-Type: application/json" \
--header "x-api-key: API_KEY_HERE" \
--data '{"assets":[{"media_id":"EXAMPLE_MEDIA_ID"},{"url":"www.path_to_png_image.com","mime_type":"image/png"}]}'

This endpoint encodes any asset type. You can either encode an asset uploaded through steg.ai or encode an asset from an URL link (External Asset). You can encode more than one asset at a time with this endpoint. MAX limit is 50 assets at a time.

Example response JSON object

{
  "message": "Request successful. Your asset will be encoded soon.",
  "data": {
    "assets": ["7e1da036-f04d-4c08-9e02-d58366d41037"]
  }
}

Request Body

Parameters

Name Type Required Description
assets array true An array that contains StegAI Asset Objects and/or External Asset Objects. Max number of items is 50.
custom object false Any custom data of key-value pairs to associate with the asset.

StegAI Asset Object

Attributes

Name Type Required Description
media_id string true The unique identifier for the asset.

External Asset Object

Attributes

Name Type Required Description
url string true URL link to an image, video, or PDF.
mime_type string true The mime_type of the link's contents. See the available types for a full list.

Response JSON Object

Attributes

Name Type Description
assets array An array of media_ids. You can use retrieve asset to see the status of the action.

Encode an Image

import base64
import json
import requests

response = requests.post("https://api.steg.ai/encode_image_async",
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  },
  data=json.dumps({
    "license": {},
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8",
    "method": 0,
    "owner": "steg.ai",
  })
)

print(response.text)
curl "https://api.steg.ai/encode_image_async" \
  -H "x-api-key: api_key_here" \
  --data-raw '{ \
    "license": {}, \
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8", \
    "method": 0, \
    "owner": "steg.ai", \
  }'
fetch(
  "https://api.steg.ai/encode_image_async",
  method: "POST",
  headers: {
    "x-api-key": "api_key_here"
  },
  body: JSON.stringify({
    "license": {},
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8",
    "method": 0,
    "owner": "steg.ai",
  })
)

The above code returns JSON structured like this:

{
    "message": "Request successful. Your image will be encoded soon.",
    "data": {
      "encode_media_id": "7e1da036-f04d-4c08-9e02-d58366d41037",
      "request_id": "c7deb911-2c7e-498f-91be-eaee25721c49"
    }
}

This endpoint encodes an image with a payload. To check the status of the encoding see get media status for more info.

Request body

Parameter Type Required Description
media_id string true The id of the media you want to encode. The value is obtained from the upload api.
owner string false The owner of the image.
license object false The license information related to the image. See license for more info.
custom object false Any key-value pair objects. See custom-data for more info.

Data object

Parameter Type Description
encode_media_id string The id of the media that is being encoded.
request_id string The id of the request. Use for get media status.

Encode a Video

import json
import requests

response = requests.post("https://api.steg.ai/encode_video",
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  },
  data=json.dumps({
    "license": {},
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8",
    "method": 0,
    "owner": "steg.ai",
  })
)

print(response.text)
curl "https://api.steg.ai/encode_video" \
  -H "x-api-key: api_key_here" \
  --data-raw '{ \
    "license": "{}", \
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8", \
    "method": "0", \
    "owner": "steg.ai", \
  }'
fetch(
  "https://api.steg.ai/encode_video",
  method: "POST",
  headers: {
    "x-api-key": "api_key_here"
  },
  body: JSON.stringify({
    "license": {},
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8",
    "method": 0,
    "owner": "steg.ai",
  })
)

The above code returns JSON structured like this:

{
    "message": "Request successful. Your video will be encoded soon.",
    "data": {
      "encode_media_id": "7e1da036-f04d-4c08-9e02-d58366d41037",
      "request_id": "c7deb911-2c7e-498f-91be-eaee25721c49"
    }
}

This endpoint encodes a video with a payload. To check the status of the encoding see get media status for more info.

Request body

Parameter Type Required Description
media_id string true The id of the media you want to encode. The value is obtained from the upload api.
owner string false The owner of the image.
license object false The license information related to the image. See license for more info.
method integer false Which method you want to encode the video with. Default is 0.
custom object false Any key-value pair objects. See custom-data for more info.

Data object

Parameter Type Description
encode_media_id string The id of the media that is being encoded.
request_id string The id of the request. Use for get media status.

Decode API

steg.ai offers three asychronous endpoints to decode images or videos.

Decode

POST /decode

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
};
const body = {
    "assets": [
        {
            "media_id": "EXAMPLE_MEDIA_ID"
        },
        {
            "url": "www.path_to_png_image.com",
            "mime_type": "image/png"
        }
    ]
};
fetch("https://api.steg.ai/decode",
    method: "POST",
    headers: headers ,
    body: JSON.stringify(body)
)
import json
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
}
body = {
    "assets": [
        {
            "media_id": "EXAMPLE_MEDIA_ID"
        },
        {
            "url": "www.path_to_png_image.com",
            "mime_type": "image/png"
        }
    ]
}
requests.post("https://api.steg.ai/decode", headers=headers, body=json.dumps(body))
curl --request POST "https://api.steg.ai/decode" \
--header "Content-Type: application/json" \
--header "x-api-key: API_KEY_HERE" \
--data '{"assets":[{"media_id":"EXAMPLE_MEDIA_ID"},{"url":"www.path_to_png_image.com","mime_type":"image/png"}]}'

Example response JSON object

{
  "message": "Request successful. Your asset will be decoded soon.",
  "data": {
    "assets": ["7e1da036-f04d-4c08-9e02-d58366d41037"]
  }
}

This endpoint decode any asset type. You can either decode an asset uploaded through steg.ai or decode an asset from an URL link (External Asset). You can decode more than one asset at a time with this endpoint. MAX limit is 50 assets at a time.

Request Body

Parameters

Name Type Required Description
assets array true An array that contains StegAI Asset Objects and/or External Asset Objects. Max number of items is 50.

StegAI Asset Object

Attributes

Name Type Required Description
media_id string true The unique identifier for the asset.

External Asset Object

Attributes

Name Type Required Description
url string true URL link to an image, video, or PDF.
mime_type string true The mime_type of the link's contents. See the available types for a full list.

Response JSON Object

Attributes

Name Type Description
assets array An array of media_ids. You can use retrieve asset to see the status of the action.

Decode an Image

import base64
import json
import requests

response = requests.post("https://api.steg.ai/decode_image_async",
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  },
  data=json.dumps({
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8"
  })
)

print(response.text)
curl "https://api.steg.ai/decode_image_async" \
  -H "x-api-key: api_key_here" \
  --data-raw '{ \
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8" \
  }'
fetch(
  "https://api.steg.ai/decode_image_async",
  method: "POST",
  headers: {
    "x-api-key": "api_key_here"
  },
  body: JSON.stringify({
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8"
  })
)

The above code returns JSON structured like this:

{
  "message": "Request successful. Your image will be decoded soon.",
  "data": {
    "request_id": "c7deb911-2c7e-498f-91be-eaee25721c49"
  }
}

This endpoint decodes an image. To check the status of the decoding see get media status for more info.

Request body

Parameter Type Required Description
media_id string true The id associated with the image. Obtained from the Upload API.

Data object

Parameter Type Description
request_id string The id of the request. Use for get media status.

Decode a Video

import base64
import json
import requests

response = requests.post("https://api.steg.ai/decode_image_async",
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  },
  data=json.dumps({
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8"
  })
)

print(response.status_code) # Returns 200
curl "https://api.steg.ai/decode_image_async" \
  -H "x-api-key: api_key_here" \
  --data-raw '{ \
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8" \
  }'
fetch(
  "https://api.steg.ai/decode_image_async",
  method: "POST",
  headers: {
    "x-api-key": "api_key_here"
  },
  body: JSON.stringify({
    "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8"
  })
)

The above code returns JSON structured like this:

{
  "message": "Request successful. Your image will be decoded soon.",
  "data": {
    "request_id": "c7deb911-2c7e-498f-91be-eaee25721c49"
  }
}

This endpoint decodes a video. To check the status of the decoding see get media status for more info.

Request body

Parameter Type Required Description
media_id string true The id associated with the video. Obtained from the Upload API.

Data object

Parameter Type Description
request_id string The id of the request. Use for get media status.

Upload API

Generate a pre-signed URL

import requests

response = requests.post("https://api.steg.ai/upload",
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  },
  data=json.dumps({
    "name": "name of file",
    "content_type": "image/png"
  })
)

print(response.status_code) # Returns 200
curl "https://api.steg.ai/upload" \
  -H "x-api-key: api_key_here" \
  --data-raw '{ \
    "name" : "name of file", \
    "content_type": "image/png" \
  }'
fetch(
  "https://api.steg.ai/upload",
  method: "POST",
  headers: {
    "x-api-key": "api_key_here"
  },
  body: JSON.stringify({
    "name": "name of file",
    "content_type": "image/png"
  })
)
{
    "message": "Send a POST request to the url"
    "data": {
        "media_id": "EXAMPLE_MEDIA_ID",
        "post_to": {
          "url": "PRESIGNED_URL",
          "fields": "PRESIGNED_FIELDS"
        },
        "ts": "09/08/2021 12:00:00",
        "expires": "09/08/2021 12:05:00"
    }
}

This endpoint generates a presigned url for you to upload your media file.

Request body

Parameter Type Required Description
name string true The name of the media file.
content_type string true The type of content the media file is. See the available types here.
request_type string false The type of request using the upload api for. The value is either "encode" or "decode".
owner string false The name of whoever owns the media file.
license object false The license information related to the media. See license for more info.

Data object

Returns an object with the following attributes:

Attribute Type Description
media_id string A unique identifier for the media.
post_to object Contains the url and form fields to make the POST request
ts datetime The time the presigned url link is generated.
expires datetime The tine the presigned url link will expire.

Upload file

import requests

with open(<file_path>, "rb") as file:
    files = {
        "file": file
    }

    requests.post(url=<PRESIGNED_URL_HERE>, files=files, data=<PRESIGNED_FIELDS>)

    print(response.status_code) # Returns 200
curl -X POST -T "/path/to/file" \
  -H "Content-Type: image/png" \
  "<PRESIGNED_URL_HERE>"

curl --location --request POST "<PRESIGNED_URL_HERE>" \
--form '<PRESIGNED_FIELDS>' \
--form 'file=@"/path/to/image"'

const uploadFormData = new FormData();
for (const [key, value] of <POST_TO_OBJECT>) {
    uploadFormData.append(key, value);
}

// Note: Append the file object
uploadFormData.append("file", <file>);

fetch(
  "<PRESIGNED_URL_HERE>", {
    method: "POST",
    body: uploadFormData
  }
)

After generating a presigned url, use the post_to object to make a POST request to upload your files.

Check Status

Get Media Status

Get the status of a request.

import requests

request_id = "example_request_id"

response = requests.get("https://api.steg.ai/media_status?request_id=request_id", 
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  }
)

print(response.status_code) # Returns 200
curl "https://api.steg.ai/media_status?request_id=example_request_id" \
  -H "x-api-key: api_key_here"
const requestId = "example_request_id";

fetch(
  "https://api.steg.ai/media_status?request_id=requestId",
  method: "GET",
  headers: {
    "x-api-key": "api_key_here"
  },
)

The above code returns JSON structured like this:

{
    "message": "request_id found.",
    "data": {
        "status": "Completed.",
        "request_type": "encode",
        "media_data": {
          "media_url": "URL_TO_IMAGE",
        }
    }
}

Querystring

Parameter Type Required Description
request_id string true The request id obtained from asynchronous endpoints.

Message values

Message string Status code
request_id found. 200
Query string parameter "request_id" is required. 400
Unable to find request item. 404
Unable to find media item associated with request. 404

Data object

Parameter Type Description
status string The status of the request. Can be the following values: "In progress.", "Error.", "Completed.".
message string Information about the get status or related to the image. Note: This is different from the message values in the section above.
request_type string The type of request being run on the media. Can be the following values: "encode" or "decode".
media_data object Data return from a completed encode, decode, or detect operation of the media. See section below for its attributes.

Media data object

Parameter request_type Type Description
image_url encode string The url to download the encode image.
owner decode string The owner of the image.
license decode object The license information related to the image. See license for more info.
custom decode object Any custom fields of the image. See custom for more info.

Usage API

Get Current Usage of the API

import requests

response = requests.get("https://api.steg.ai/usage", 
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  }
)

print(response.status_code) # Returns 200
curl "https://api.steg.ai/usage" \
  -H "x-api-key: api_key_here"
fetch(
  "https://api.steg.ai/usage",
  method: "GET",
  headers: {
    "x-api-key": "api_key_here"
  }
)

The above code returns JSON structured like this:

{
  {
    "message": 3,
    "data": [
        {
            "media_id": "d051f164-b066-4702-8343-c61ba098ba63",
            "ts": "01/05/2021 16:54:24",
            "endpoint": "encode_image",
            "status_code": 200
        },
        {
            "media_id": "e5c57510-d2e2-4cc8-afb4-b3ce1fa77b71",
            "ts": "01/05/2021 17:12:15",
            "endpoint": "encode_image",
            "status_code": 200
        },
        {
            "ts": "01/05/2021 17:27:58",
            "endpoint": "encode_image",
            "status_code": 400
        },
    ]
  }
}

This endpoint returns the usage of each endpoint and the status code for steg.ai API.

Querystring

Use querystrings to get more specific usage data of a date or of an endpoint.

Parameter Type Required Description
start string false The start date to view the usage of. Format needs to be YYYY-MM-DD.
end string false The end date to view the usage of. Format needs to be YYYY-MM-DD.

The start and end querystrings needs to be in this format: YYYY-MM-DD. Must contain the year while month and day are optional.

Data object

Attribute Type Required Description
message integer true The total number of items in the data array.
endpoint string true The name of the endpoint.
status_code integer true The status code returned when the endpoint was called.
ts date true The date and time the endpoint was accessed. Format: YYYY-MM-DD HH:MM:SS.
media_id string false A unique identifier for the media. Only appears if the request was success.

Asset API

Assets is a collection of media (image or video) you have uploaded.

Retrieve All Assets

import requests

response = requests.get("https://api.steg.ai/asset",
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  }
)

print(response.text)
curl "https://api.steg.ai/asset" \
  -H "x-api-key: api_key_here"
fetch(
  "https://api.steg.ai/asset",
  method: "GET",
  headers: {
    "x-api-key": "api_key_here"
  }
)
{
    "message": 7
    "data": [
        {
            "ts": "03/12/2021 15:58:03",
            "license": {
                "editorial": false,
                "commercial": true,
                "expiration": "2021-03-09T17:49:46.117Z",
                "type": "Royalty Free",
                "url": "https://en.wikipedia.org/wiki/Royalty-free",
                "info": "Royalty-free (RF) material subject to copyright or other intellectual property rights may be used without the need to pay royalties or license fees for each use, per each copy or volume sold or some time period of use or sales."
            },
            "size": 159779,
            "version": 2,
            "path" : "URL_TO_IMAGE",
            "thumbnail" : "URL_TO_THUMBNAIL",
            "status": true,
            "owner": "steg.ai",
            "media_id": "30bbab94-5e0d-4639-9bdf-acbf55812d61"
        },
        . . .
    ],
    "next_key": "EXAMPLE_PAGE_KEY"
}

This endpoint returns all media files you have uploaded and each one's associated data. Limits to 25 per request.

Querystring

Parameter Type Required Description
next string false The key to retrieve the next set of media.

Message

Contains the total number of media you have uploaded.

Data object

Attribute Type Description
license object The license information related to the media. See license for more info.
media_id string A unique identifier for the media.
media_type string Whether the media is an image or video.
name string The filename of the media.
owner string The owner of the media.
path string The url of the media.
size integer The size of the media.
status boolean If the media have been encoded or not.
thumbnail string The thumbnail url of the media.
ts date The date and time the media have been last edited. Format: YYYY-MM-DD HH:MM:SS.
upload_date date The date and time the media have been uploaded.
version integer The current version of the media.

Next key

This value is used for pagination and is only included in the response when there are more media files that can be retrieved. Include it in the next query param in a subsequent call to the endpoint to retrieve the next set of media files. Repeat until the value is no longer provided and you will have every media file. NOTE: This endpoint does not sort on any particular field, so if a specific sort order is required you must fetch all items and sort them yourself. Ability to sort the result set within the call is being actively worked on.

Retrieve an Asset

import requests

response = requests.get("https://api.steg.ai/asset?media_id=30bbab94-5e0d-4639-9bdf-acbf55812d61",
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  }
)

print(response.text)
curl "https://api.steg.ai/asset?media_id=30bbab94-5e0d-4639-9bdf-acbf55812d61" \
  -H "x-api-key: api_key_here"
fetch(
  "https://api.steg.ai/asset?media_id=30bbab94-5e0d-4639-9bdf-acbf55812d61",
  method: "GET",
  headers: {
    "x-api-key": "api_key_here"
  }
)
{
    "message": 1
    "data": [
        {
            "license": {
                "editorial": false,
                "commercial": true,
                "expiration": "2021-03-09T17:49:46.117Z",
                "type": "Royalty Free",
                "url": "https://en.wikipedia.org/wiki/Royalty-free",
                "info": "Royalty-free (RF) material subject to copyright or other intellectual property rights may be used without the need to pay royalties or license fees for each use, per each copy or volume sold or some time period of use or sales."
            },
            "media_id": "30bbab94-5e0d-4639-9bdf-acbf55812d61",
            "media_type": "image",
            "name": "download20211106144008.png",
            "original": "URL_TO_ORIGINAL_IMAGE",
            "owner": "steg.ai",
            "path" : "URL_TO_IMAGE",
            "size": 159779,
            "status": true,
            "thumbnail" : "URL_TO_THUMBNAIL",
            "ts": "11/19/2021 15:04:14",
            "upload_date": "11/19/2021 15:04:14",
            "version": 2
          },
    ]
}

This endpoint returns the data associated with a specific media.

Request body

Parameter Type Required Description
media_id string true The unique identifier for the media.

Message

Contains the total number of media you have retrieved. Will always be 1.

Data object

Attribute Type Description
license object The license information related to the media. See license for more info.
media_id string A unique identifier for the media.
media_type string Whether the media is an image or video.
name string The filename of the media.
original string The url path of the original media.
owner string The owner of the media.
path string The url of the encoded media.
size integer The size of the media.
status boolean If the media have been encoded or not.
thumbnail string The thumbnail url of the media.
ts date The date and time the media have been last edited. Format: MM/DD/YYYY HH:MM:SS.
upload_date date The date and time the media have been uploaded. Format: MM/DD/YYYY HH:MM:SS.
version integer The current version of the media.

Delete an Asset

import requests

response = requests.delete("https://api.steg.ai/asset",
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  },
  data=json.dumps({
    "media_id" : "EXAMPLE_MEDIA_ID"
  })
)

print(response.text)
curl "https://api.steg.ai/asset" \
  -X DELETE -H "x-api-key: api_key_here"
  --data-raw '{
    "media_id" : "EXAMPLE_MEDIA_ID"
  }'
fetch(
  "https://api.steg.ai/asset,
  method: "DELETE",
  headers: {
    "x-api-key": "api_key_here"
  },
  body: JSON.stringify({
    "media_id" : "EXAMPLE_MEDIA_ID"
  })
)

The above code returns JSON structured like this:

{
    "message": "True",
    "data": {}
}

This endpoint delete a media.

Request body

Parameter Type Required Description
media_id string true A unique identifier for the media.

Data object

Returns an empty object.

Update an Asset

import requests

response = requests.post("https://api.steg.ai/asset",
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  },
  data=json.dumps({
    "media_id" : "EXAMPLE_MEDIA_ID",
    "owner" : "new owner"
  })
)

print(response.text)
curl "https://api.steg.ai/asset" \
  -X POST -H "x-api-key: api_key_here" \
  --data-raw '{ \
    "media_id" : "EXAMPLE_MEDIA_ID", \
    "owner" : "new owner' \
  }'
fetch(
  "https://api.steg.ai/asset,
  method: "POST",
  headers: {
    "x-api-key": "api_key_here"
  },
  body: JSON.stringify({
    "media_id" : "EXAMPLE_MEDIA_ID",
    "owner" : "new owner"
  })
)

The above code returns JSON structured like this:

{
    "message": "Successfully updated data",
    "data": {
        "media_id": "EXAMPLE_MEDIA_ID",
    }
}

This endpoint updates data associated with a media. Any parameter listed below (except media_id) can be updated.

Request body

Parameter Type Required Description
media_id string true A unique identifier for the media.
owner string false The owner of the media.
license object false The license information related to the media. See license for more info.
custom object false Any custom data of key-value pairs to associate with the media.

Data object

Parameter Type Description
media_id string A unique identifier for the media.

History API

Get the History of an Asset

import requests

response = requests.get("https://api.steg.ai/history?media_id=EXAMPLE_MEDIA_ID", 
  headers={
    "Content-Type" : "application/json",
    "x-api-key" : "api_key_here"
  }
)

print(response.text) # Returns 200
curl "https://api.steg.ai/history?media_id=EXAMPLE_MEDIA_ID" \
  -H "x-api-key: api_key_here"
fetch(
  "https://api.steg.ai/history?media_id=EXAMPLE_MEDIA_ID",
  method: "GET",
  headers: {
    "x-api-key": "api_key_here"
  }
)
{
    "message": 1
    "data": [
        {
            "change": {
                "owner": {
                    "new": "Joe", 
                    "old": "Evan"
                }
            },
            "new" : {},
            "ts": "03/12/2021 15:58:03",
            "license": {
                "editorial": false,
                "commercial": true,
                "expiration": "2021-03-09T17:49:46.117Z",
                "type": "Royalty Free",
                "url": "https://en.wikipedia.org/wiki/Royalty-free",
                "info": "Royalty-free (RF) material subject to copyright or other intellectual property rights may be used without the need to pay royalties or license fees for each use, per each copy or volume sold or some time period of use or sales."
            },
            "size": 159779,
            "version": 2,
            "path" : "URL_TO_IMAGE",
            "status": true,
            "owner": "Among Us",
            "id": "30bbab94-5e0d-4639-9bdf-acbf55812d61"
        },
    ]
}

This endpoint returns the history of an asset. It will show all the new and updated data associated with an asset.

Querystring

Parameter Type Required Description
media_id string true A unique identifier for the media.

Data object

Returns an array of objects with the following attributes:

Attribute Type Description
change object An object contains the changes of the media's version number compared to its previous version. See change for more info.
license object The license information related to the media. See license for more info.
new object An object contains all the new data associated with the media's version number.
ts date The date and time the media have been edited/uploaded. Format: YYYY-MM-DD HH:MM:SS.
version integer The current version of the media.
path string The url of the media's version number.
status boolean If the media have been encoded or not.
owner string The owner of the media's version number.
media_id string A unique identifier for the media.

Change object

The change object is a key-value object where the key is the field that's been changed and the value is the structured in the following:

Attribute Type Description
new string The current value of the field.
old string The previous value of the field.

Webhooks API

Webhooks are a way for one application to notify another about specific events or updates automatically. Instead of actively checking for changes (for example using check status), your application subscribes to certain events, and when those events occur, a notification (HTTP POST request) is sent to a predefined URL.

Events

A webhook event refers to a specific occurrence that triggers the delivery of a notification to a designated URL.

Available event types

Name Description
encode.success Triggers after an encoding is finished.
decode.success Triggers after a decoding is finished.

Receiving events

Example POST Request from Steg

POST /webhook-endpoint HTTP/1.1
Host: example.com
Content-Type: application/json
X-StegAI-Signature: t=1611144604,s=6b7f9dc426e59fbc186502ea33f272fbca14a0d169f237d3575c2ae0befb2704

{
  "event_type": "encode.success",
  "media_id": "eabb1b2c-e380-409b-a29b-62608aa695a8"
}

All webhook events received by your URL will have a timestamp and signature in the header: X-StegAI-Signature. This is used to verify that the request came from StegAI and not from a malicious attacker. Check out our how-to guide on how to verify the signature. The signature is generated by concatenating the timestamp, a dot (’.’), and the JSON-encoded payload into a string. That string is then hashed with the secret key using HMAC SHA256.

The secret key for a webhook is generated when you first create the webhook subscription using POST /webhook. The designated URL will receive the secret key and it is recommended that you save that secret key into your system.

Your URL must return a status code: 200; otherwise, we will retry sending the same event.

Parameters

Name Type Description
t= timestamp The timestamp of when the webhook event is sent.
s= signature The hashed signature of the webhook event.

Body

Parameters

Name Type Description
event_type string The event type the webhook is subscribed to.
media_id string The unique identifier of the asset that triggered the webhook.

Webhooks retry

If your URL does not return a 200 status code to us, we implement an exponential backoff policy. This policy increases the delay between each attempt to send the webhook event to your URL. After the initial failure, we will try again in 2 hours from the initial time. If that attempt fails, another attempt is made after 4 hours. Subsequently, attempts are made after 8 hours, and finally after 16 hours. If after the 4th attempt your URL still returns a non-200 status code, we delete the webhook message and mark it as a failure.

Get Webhook Events List

GET /webhook/events

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
};

fetch("https://api.steg.ai/webhook/events",
    method: "GET",
    headers: headers
)
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
}

requests.get("https://api.steg.ai/webhook/events", headers=headers)
curl --request GET "https://api.steg.ai/webhook/events" \
--header "Content-Type: application/json" \
--header "x-api-key: API_KEY_HERE"

This endpoint returns a list of event types that you can subscribe to. The values are used in creating a webhook subscription.

Example response JSON object

{
  "message": "Use one of the following values in `events` for POST /webhook'",
  "data": {
      "events": ["encode.success", "decode.success"]
  }
}

Response JSON object

Attributes

Name Type Description
events array The event types available to subscribe to.

Get Webhook Subscriptions

GET /webhook

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
};

fetch("https://api.steg.ai/webhook",
    method: "GET",
    headers: headers
)
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
}

requests.get("https://api.steg.ai/webhook", headers=headers)
curl --request GET "https://api.steg.ai/webhook" \
--header "Content-Type: application/json" \
--header "x-api-key: API_KEY_HERE"

This endpoint returns all the webhooks you have subscribed to.

Example response JSON object

{
  "message": 1,
  "data": {
      "webhooks": [
          {
              "id": "54244b6a-87c2-4de5-87c6-ccf77ca390c2",
              "event_type": "encode.success",
              "url": "https://yourdomain.com/custom_endpoint"
          }
      ]
  }
}

Response JSON object

Attributes

Name Type Description
message integer The number of webhooks to which you are subscribed.
id string A unique identifier for the webhook subscription.
event_type string The event types that the webhook is subscribed to.
url string The URL that the webhook is sending POST requests to.

Create Webhook Subscription

POST /webhook

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
};
const body = {
    "event": "encode.success",
    "url": "https://yourdomain.com/custom_endpoint"
};
fetch("https://api.steg.ai/webhook",
    method: "POST",
    headers: headers ,
    body: JSON.stringify(body)
)
import json
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
}
body = {
    "event": "encode.success",
    "url": "https://yourdomain.com/custom_endpoint"
}
requests.post("https://api.steg.ai/webhook", headers=headers, body=json.dumps(body))
curl --request POST "https://api.steg.ai/webhook" \
--header "Content-Type: application/json" \
--header "x-api-key: API_KEY_HERE" \
--data '{"event":"encode.success","url":"https://yourdomain.com/custom_endpoint"}'

This endpoint creates a webhook subscription. Webhook subscriptions support the creation of one event at a time in the body.

This endpoint sends a POST request to your URL with the following header: X-Hook-Secret: secret_key. We recommend you save the secret key into your database. Your URL will need to return the same header value and a status code: 200 in order to successfully create the webhook subscription.

Example response JSON object

{
  "message": "",
  "data": {
      "id": "54244b6a-87c2-4de5-87c6-ccf77ca390c2",
      "event_type": "encode.success",
      "url": "https://yourdomain.com/custom_endpoint"
  }
}

Request JSON object

Parameters

Name Type Required Description
event string true The type you want to subscribe to.
url string true The URL that you want the webhook to send POST requests to.

Response JSON object

Attributes

Name Type Description
id string A unique identifier for the webhook subscription.
event_type string The event types that the webhook is subscribed to.
url string The URL that the webhook is sending POST requests to.

Delete Webhook Subscription

DELETE /webhook/:id

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
};

fetch("https://api.steg.ai/webhook/:id",
    method: "DELETE",
    headers: headers
)
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "API_KEY_HERE"
}

requests.delete("https://api.steg.ai/webhook/:id", headers=headers)
curl --request DELETE "https://api.steg.ai/webhook/:id" \
--header "Content-Type: application/json" \
--header "x-api-key: API_KEY_HERE"

This endpoint deletes a webhook subscription.

Example response JSON object

{
  "message": "True",
  "data": {}
}

Request path

Parameters

Name Type Required Description
id string true The unique identifier of the webhook you want to delete.

Response JSON object

Returns an empty object.

WebSockets API

steg.ai presents a WebSocket api in order to receive real-time messages from actions such as protecting/authenticating images or videos. For example, clients connected to the WebSocket will receive messages when a video is done protecting.

List of available actions

The WebSocket has a limited set of actions compared to the REST API.

Auth

Use this route to authenticate the WebSocket connection. Required to use the rest of actions.

Send the following message to the WebSocket:


{
    "action": "auth", 
    "apiKey": "api_key_here"
}

Returns


{
    "statusCode": 200, 
    "body": "{"message": "Authenicated"}"
}

Decode

Use this route to decode a media. This route will continue to update you on the progress as long as you're still connected to the WebSocket connection.

Send the following message to the WebSocket:


{
    "action":"decode", 
    "media_id": "30bbab94-5e0d-4639-9bdf-acbf55812d61", 
    "media_type": "image", 
    "method": 0, 
    "force": true
}

Ping

Use this route to keep the WebSocket connection alive.

Send the following message to the WebSocket:


{
    "action": "ping"
}

Returns


{
    "statusCode": 200, 
    "body": "{"message": "pong"}"
}

Subscribe

Use this route to keep track of an event (encode, decode) of an asset.

Send the following message to the WebSocket:


{
    "action": "subscribe", 
    "id": "c7deb911-2c7e-498f-91be-eaee25721c49"
}

Returns the following if the request_id is from an encode event:


{
    "statusCode": 200,
    "body": "{
        "request_id": "c7deb911-2c7e-498f-91be-eaee25721c49",
        "data": {
            "image": "url_to_encode_image_here",
        },
        "status": "Completed."
    }"
}

Returns the following if the request_id is from a decode event:


{
    "statusCode": 200,
    "body": "{
        "request_id": "c7deb911-2c7e-498f-91be-eaee25721c49",
        "data": {
            "license": {
                "editorial": false,
                "expiration": "12/20/2025",
                "commercial": true,
                "type": "Creative Commons",
                "url": "http://creativecommons.org/licenses/by/4.0/",
                "info": "Creative Commons licenses give everyone from individual creators to large institutions a standardized way to grant the public permission to use their creative work under copyright law."
            },
            "ts": "11/19/2021 15:04:14",
            "upload_date": "11/19/2021 15:04:14",           
            "owner": "danny",
        },
        "status": "Completed."
    }"
}

Non-existent Routes

If the action parameter in the messages is not one of the above or mispelled, the following error would appear


{
    "statusCode": 400,
    "body": "Route doesn't exist. Check docs for more information."
}

License Object

The license object contains the data related to the licensing of a particular media.

The object has the following attributes:

Attribute Type Description
editorial boolean If the media can be used for editorial purposes.
commercial boolean If the media can be used for commercial purposes.
expiration date The date when the license expires.
type string The type of license. Can be one of the following: Creative Commons, Royalty Free, Copyright Free, Public Domain
url string The url to the license.
info string Additional info about the license.

Content Types

The following table are the file content types we currently support to encode:

Name MIME Type Extension
Portable Document Format (PDF) application/pdf .pdf
Bitmap (BMP) image/bmp .bmp
Graphics Interchange Format (GIF) image/gif .gif
ICO image/x-icon .ico
Joint Photographic Experts Group (JPEG) image/jpeg .jpg, .jpeg, .jfif, .pjpeg, .pjp
Portable Network Graphics (PNG) image/png .png
Tag Image File Format (TIFF) image/tiff .tif, .tiff
Web Picture Format (WEBP) image/webp .webp
Motion Picture Experts Group (MPEG) video/mpeg .mpeg
MP4 video/mp4 .mp4
Quicktime Movie (MOV) video/quicktime .mov

Errors

The steg.ai API uses the standard HTTP response codes to indicate success or failure of an API request. A 200 shows a successful request. But a 4xx range means an error from the client (e.g. invalid parameters for a request). Codes in 5xx range means there's an error on steg.ai API's.

The steg.ai API uses the following error structure:

{
    "error": {
        "message": "Image is not a valid base64 string.",
        "type": "params_invalid"
    }
}

The above error code would return a 400 status code.

Attributes

Attribute Type Description
message string The error message. Contains a helpful message on why the request failed.
type string The error type. Scroll to Error Types for more information.

HTTP Status Codes

Error Code Meaning
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your API key is wrong.
403 Forbidden -- The method requested is hidden for administrators only.
404 Not Found -- The specified method could not be found.
405 Method Not Allowed -- You tried to access an invalid method.
500 Internal Server Error -- We had a problem with our server. Try again later.

Error Types

Error Type Meaning
params_invalid The parameters included in the request are invalid. Make sure the parameters are the correct type and value.
invalid_request The request you made doesn't support this method. Make sure the request method is correct.
authenication_error The api key included in the request is invalid or not set. Make sure the api key is correct and in the headers.
api_error API errors cover any other type of problem (e.g., a temporary problem with steg.ai's servers), and are extremely uncommon.