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.
Header
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
- decode
- ping
- subscribe
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 | |
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. |