Steg.AI Logo
  • Leak Prevention & Tracing
  • Deepfake Detection
  • Content Authentication
  • Copyright Protection
  • About
  • Careers
  • Contact
  • News
API
Sign In Request a Demo
Steg.AI Logo

  • Leak Prevention & Tracing
  • Deepfake Detection
  • Content Authentication
  • Copyright Protection

  • About
  • Careers
  • Contact
  • News

API

Request a Demo

Log In
    INTRODUCTION
    AUTHENTICATION
    ERRORS
    PAGINATION
    DECODE Decode Async and Batch Decode
    ENCODE Encode Forensic Watermark Visible Watermark Async and Batch Encode
    UPLOAD Generate a presigned URL Upload file
    USAGE Get Usage of the API
    WEBHOOKS Events Receiving Events Webhooks Retry Get Webhook Events List Get Webhook Subscriptions Create Webhook Subscription Delete Webhooks Subscription
    ASSET Retrieve All Assets Retrieve Asset Delete Assets Delete Asset Update Asset
    CHECK STATUS Get Status
    CONTENT TYPES Supported Asset List
    HOW TO GUIDES How to Forensic Watermark an Image How to Visible Watermark an Image How to Decode an Image How to Subscribe to a Webhook Event

Introduction

Welcome to the documentation for the Steg AI API. The Steg AI API conforms to the design principals of the representational state transfer (REST) architectural style. Our API has resource-oriented URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.

Base URL
https://api.steg.ai

Authentication

The Steg AI API uses API keys to authenticate requests. All API requests expect an API key to be included in the header. Requests sent without an API key will fail. Moreover, all API requests must be made over HTTPS. Requests made over HTTP will fail.


Use your API key by assigning it to x-api-key in the request header.


Your API keys hold many privileges, and it is imperative that you keep them secure. Do not share your API keys publicly; for example, in client-side code or code repositories like Github.


To register a new API key, contact us.

authenticate with api key in header

import requests

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

requests.get("https://api.steg.ai/<ENDPOINT>", headers=headers)
        

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

fetch("https://api.steg.ai/<ENDPOINT>",
    method: "GET",
    headers: headers 
)
        

curl --request GET "https://api.steg.ai/<ENDPOINT>" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" 
        

Errors

When you make a request to the Steg AI API, a response status code and JSON object are returned. The response status code indicates success or failure of the API request. The JSON object provides additional information in the event of a failure.

HTTP Response Status Codes

The Steg AI API uses standard HTTP response status codes. Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error from the client (for example, because an invalid parameter was provided). Codes in the 5xx range indicate an error with Steg’s servers.

Response JSON Object

The response JSON object is populated in the event of an error; specifically, a status code in the 4xx or 5xx range.

Attributes


message string
A human-readable message providing additional details on why the request failed.

type enum[string]
An enum that specifies the type of the error returned. Possible enum values are api_error, authenticate_error, invalid_request, invalid_parameter.

http status code summary
200OKEverything worked as expected.
400Bad RequestThe request was not accepted. This is usually because a required parameter was missing.
401UnauthorizedNo valid API key provided.
403ForbiddenThe API key does not have permissions to perform the request.
404Not FoundThe requested endpoint does not exist.
405Method Not AllowedThe requested endpoint does not allow this method.
500Server ErrorSomething went wrong on Steg’s end.
response json object
{
    "error": {
        "message": "'asset_id' is missing.",
        "type": "invalid_parameter"
    }
}
error types
api_errorA catch-all for API errors not covered by the other error types.
authenication_errorThe API key included in the request isinvalid or not set.
invalid_requestThe request does not support this method.
invalid_paramsAt least one parameter in the request is missing or invalid.

Pagination

Pagination is a technique used in APIs to manage large datasets returned by queries. When an API resource has an extensive list of objects, pagination helps break down the results into smaller, more manageable chunks. The Steg AI API implements pagination through the use of query string parameters in the request URL. Clients can control the pagination of results by specifying the next and limit parameters.


For example, calling the GET /usage endpoint will only return the 25 most recent usage of the Steg AI API. But if you have made 100 calls to the API, you would need to use pagination to retrieve all the results.

Query Strings

Parameters


next string
The key to retrieve the next set of items in the data array.

limit int
Number of items in the data array to return. Default is 25. Max value is 100.

example of using pagination

import json
import requests

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

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

usage = []
params = {}

while True:
  response = requests.get(f"{BASE_URL}/usage", headers=headers, params=params)
  reponse_data = response.json()
  next_key = reponse_data.get("next_key")

  # No more data to retrieve if "next_key" is null
  if not next_key:
      break

  # Use the "next" to retrieve the next set of items
  params["next"] = next_key
  usage += reponse_data.get("data")

print(len(usage)) # Will have all the results


const BASE_URL = "https://api.steg.ai";
const APIKEY = "api_key_here";

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

let usage = [];
let params = {};

(async () => {
  while (true) {
      const queryString = new URLSearchParams(params).toString();
      const response = await fetch(BASE_URL + "/usage?" + queryString, { headers });
      const responseData = await response.json();
      const nextKey = responseData.next_key;

      // No more data to retrieve if "next_key" is null
      if (!nextKey) {
          break;
      }

      // Use the "next" to retrieve the next set of items
      params.next = nextKey;
      usage = [...usage, ...responseData.data];
  }

  console.log(usage.length); // Will have all the results
})();


#!/bin/bash

# Set your API key
APIKEY="your_api_key_here"

# Set your base URL
BASE_URL="https://api.example.com"

# Set your initial headers
headers=(
  "Content-Type: application/json"
  "x-api-key: $APIKEY"
)

# Initialize the list for storing usage data
usage=()

# Initialize an empty params dictionary
declare -A params

# Loop until there is no more data to retrieve
while true; do
  # Make a GET request to retrieve usage data
  response=$(curl -X GET "${BASE_URL}/usage" -H "${headers[@]}" --data-urlencode "$(declare -p params)")

  # Parse the JSON response
  response_data=$(echo "$response" | jq -r '.')
  next_key=$(echo "$response_data" | jq -r '.next_key')

  # Exit the loop if there is no more data to retrieve
  if [ "$next_key" = "null" ]; then
      break
  fi

  # Use the "next" key to retrieve the next set of items
  params["next"]=$next_key

  # Append the usage data to the usage list
  usage+=($(echo "$response_data" | jq -r '.data[]'))
done

# Print the length of the usage list
echo "${#usage[@]}"

decode

decode

This endpoint decodes any and all supported asset types. You can either decode an asset uploaded through the Steg AI upload endpoint or by using a URL. You can also specify whether the request should be synchronous or asynchronous using the async property. This endpoint also supports batch decoding with a limit of 50 assets per request. For batch decodes, all requests will be handled asynchronously.

Request Body

Parameters


assets array[InternalAsset|ExternalAsset] Required
An array of InternalAsset and/or ExternalAsset objects. Max number of items is 50.

async boolean
Indicates whether to handle the request asynchronously or not. The default is false.

InternalAsset Object

Attributes


asset_id string Required
The unique identifier for the asset that was returned from the upload endpoint.

ExternalAsset Object

Attributes


url string Required
URL to a supported asset type.

mime_type string Required
The mime_type of the url contents. See the available types here.



Response JSON Object

Attributes


request_id string
The unique identifier of the request. Used for status endpoint.

data array[DecodeAsset]
An array of DecodeAsset objects.

DecodeAsset Object

Attributes


original_asset string
The asset_id of the InternalAsset or the url of the ExternalAsset that was decoded.

source enum[string]
An enum indicating where the original_asset came from. Possible values are steg and external.

asset_id_found string
The unique identifier of the watermarked asset found after decoding.

data_found dict
The key-value pairs associated with the asset.

post /decode

import json
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
}
body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_ID"
        },
        {
            "url": "www.path_to_png_image.com",
            "mime_type": "image/png"
        }
    ],
    "async": False
}
requests.post("https://api.steg.ai/decode", headers=headers, body=json.dumps(body))
        

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

curl --request POST "https://api.steg.ai/decode" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" \ 
--data '{"assets":[{"asset_id":"EXAMPLE_ASSET_ID"},{"url":"www.path_to_png_image.com","mime_type":"image/png"}],"async":false}'
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID",
  "data": [
      {
          "original_asset": "EXAMPLE_ASSET_ID",
          "source": "STEG",
          "asset_id_found": "c20007c5-fe03-4db8-b394-c874d570cdab",
          "data_found": {
              "key": "value"
          }
      },
      {
          "original_asset": "www.path_to_png_image.com",
          "source": "EXTERNAL",
          "asset_id_found": "9d4f2190-a10b-4c82-b939-77649b9ef7b5",
          "data_found": {
              "key": "value"
          }
      }
  ]
}

async and batch decode

If more than one asset is provided for a batch request or the async flag is set to true, we will handle the request asynchronously. To handle asynchronous requests, we recommend using our webhooks API. To setup webhooks for handling batch decode requests, you should subscribe to the decode.success event.


If you are unable to use the webhooks, we provide an alternative approach based on polling. When we receive a batch decode request, we return a request_id. The request_id can be used with the status endpoint to check on the status of the batch decode. See the status endpoint for more information.

Response JSON Object

Attributes


request_id string
The unique identifier of the request. Used for status endpoint.

post /decode

import json
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
}
body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_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))
        

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
};
const body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_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)
)
        

curl --request POST "https://api.steg.ai/decode" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" \ 
--data '{"assets":[{"asset_id":"EXAMPLE_ASSET_ID"},{"url":"www.path_to_png_image.com","mime_type":"image/png"},"..."]}'
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID"
}

encode

encode

This endpoint encodes any and all supported asset types. You can either encode an asset uploaded through the Steg AI upload endpoint or by using a URL. This endpoint also supports batch encoding with a limit of 50 assets per request.


Each encoded asset can have some combination of multiple visible watermarks applied and one forensic watermark applied. To apply visible watermarks, VisibleOptions objects should be added to the visible array attribute of the InternalAsset or ExternalAsset objects. These watermarks will be applied from first to last.


For forensic watermarks, only one forensic watermark can be applied to each asset. To apply a forensic watermark, a ForensicOptions object should be added to the forensic array attribute of the InternalAsset or ExternalAsset objects. The forensic watermark will be applied after any visible watermarks.

Request Body

Parameters


assets array[InternalAsset|ExternalAsset]
An array of InternalAsset and/or ExternalAsset objects. Max number of items is 50.

async boolean
Indicates whether to handle the request asynchronously or not. The default is false.

InternalAsset Object

Attributes


asset_id string Required
The unique identifier for the asset that was returned from the upload endpoint.

forensic array[ForensicOptions]
An array of ForensicOptions objects. If at least one object is in this array, then a unique forensic watermark will be applied to the asset. At this time, Steg AI only supports applying one forensic watermark per asset, so this array should never contain more than one ForensicOptions object. Additional objects in the array will be ignored.

visible array[VisibleOptions]
An array of VisibleOptions objects. For each VisibleOptions object in this array, a visible watermark will be applied to the asset.

ExternalAsset Object

Attributes


url string Required
URL to a supported asset type.

mime_type string Required
The mime_type of the url contents. See the available types here.

forensic array[ForensicOptions]
An array of ForensicOptions objects. If at least one object is in this array, then a unique forensic watermark will be applied to the asset. At this time, Steg AI only supports applying one forensic watermark per asset, so this array should never contain more than one ForensicOptions object. Additional objects in the array will be ignored.

visible array[VisibleOptions]
An array of VisibleOptions objects. For each VisibleOptions object in this array, a visible watermark will be applied to the asset.



Response JSON Object

Attributes


request_id string
The unique identifier of the request. Used for status endpoint.

data array[EncodeAsset]
An array of EncodeAsset objects.

EncodeAsset Object

Attributes


original_asset string
The asset_id of the InternalAsset or the url of the ExternalAsset that was watermarked.

source enum[string]
An enum indicating where the original_asset came from. Possible values are steg and external.

asset_id string
The unique identifier of the watermarked asset.

watermarked_path string
A downloadable URL to the watermarked asset.

post /encode

import json
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
}
body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_ID",
            "forensic": [
                {
                    "data": {
                        "vendor": "Vendor A",
                        "use": "graphics only"
                    }
                }
            ]
        },
        {
            "url": "www.path_to_png_image.com",
            "mime_type": "image/png",
            "visible": [
                {
                    "type": "repeat",
                    "text": "Do not share",
                    "direction": "horizontal"
                }
            ]
        }
    ],
    "async": False
}
requests.post("https://api.steg.ai/encode", headers=headers, body=json.dumps(body))
        

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
};
const body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_ID",
            "forensic": [
                {
                    "data": {
                        "vendor": "Vendor A",
                        "use": "graphics only"
                    }
                }
            ]
        },
        {
            "url": "www.path_to_png_image.com",
            "mime_type": "image/png",
            "visible": [
                {
                    "type": "repeat",
                    "text": "Do not share",
                    "direction": "horizontal"
                }
            ]
        }
    ],
    "async": false
};
fetch("https://api.steg.ai/encode",
    method: "POST",
    headers: headers , 
    body: JSON.stringify(body)
)
        

curl --request POST "https://api.steg.ai/encode" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" \ 
--data '{"assets":[{"asset_id":"EXAMPLE_ASSET_ID","forensic":[{"data":{"vendor":"Vendor A","use":"graphics only"}}]},{"url":"www.path_to_png_image.com","mime_type":"image/png","visible":[{"type":"repeat","text":"Do not share","direction":"horizontal"}]}],"async":false}'
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID",
  "data": [
      {
          "original_asset": "EXAMPLE_ASSET_ID",
          "source": "STEG",
          "watermarked_asset_id": "c20007c5-fe03-4db8-b394-c874d570cdab",
          "watermarked_path": "URL_TO_WATERMARKED_ASSET"
      },
      {
          "original_asset": "www.path_to_png_image.com",
          "source": "EXTERNAL",
          "watermarked_asset_id": "9d4f2190-a10b-4c82-b939-77649b9ef7b5",
          "watermarked_path": "URL_TO_WATERMARKED_ASSET"
      }
  ]
}

forensic watermark

Forensic watermarking is a technique used to embed hidden information into digital assets. These watermarks are unique to each piece of content and are designed to be robust against various forms of manipulation or alteration.


Steg AI provides the forensic attribute in the InternalAsset or ExternalAsset objects of our encode endpoint to allow you to add forensic watermarks to your assets. The forensic attribute should contain one ForensicOptions object in the array to create a forensic watermark on the asset. At this time, Steg AI only supports adding one forensic watermark per asset; so, if multiple ForensicOptions objects are in the array, only the first one is used.

ForensicOptions Object

Attributes


data object
Any custom data of key-value pairs to associate with the asset.

post /encode

import json
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
}
body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_ID",
            "forensic": [
                {
                    "data": {
                        "vendor": "Vendor A",
                        "use": "graphics only"
                    }
                }
            ]
        }
    ]
}
requests.post("https://api.steg.ai/encode", headers=headers, body=json.dumps(body))
        

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
};
const body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_ID",
            "forensic": [
                {
                    "data": {
                        "vendor": "Vendor A",
                        "use": "graphics only"
                    }
                }
            ]
        }
    ]
};
fetch("https://api.steg.ai/encode",
    method: "POST",
    headers: headers , 
    body: JSON.stringify(body)
)
        

curl --request POST "https://api.steg.ai/encode" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" \ 
--data '{"assets":[{"asset_id":"EXAMPLE_ASSET_ID","forensic":[{"data":{"vendor":"Vendor A","use":"graphics only"}}]}]}'
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID",
  "data": {
    "assets": [
      {
          "original_asset": "EXAMPLE_ASSET_ID",
          "source": "STEG",
          "watermarked_asset_id": "c20007c5-fe03-4db8-b394-c874d570cdab",
          "watermarked_path": "URL_TO_WATERMARKED_ASSET"
      }
    ]
  }
}

visible watermark

Visible watermarking applies a visible mask on top of the content of the asset. These watermarks intentionally spoil the content of the asset and are often used to deter unauthorized use or distribution.


Steg AI provides the visible attribute in the InternalAsset or ExternalAsset objects of our encode endpoint to allow the creation of a visible watermark on the encoded asset. The visible attribute must contain at least one VisibleOptions object in the array to create a visible watermark on the asset. The visible watermarks are applied in the order of the VisibleOptions objects in the array, with the first option in the array applied first and then the next item applied on top and so on.

VisibleOptions Object

Attributes


type enum[string]
An enum that specifies the type of text that appears on the asset. Possible values are repeat and single.

text string
The text that is displayed in the visible watermark.

direction enum[string]
Only available if type attribute is repeat. Direction of the repeat text. Possible enum values horizontal and diagonal.

position enum[string]
Only available if type attribute is single. Position of the single text. Possible enum values are bottom, top, left, right, and center.

post /encode

import json
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
}
body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_ID",
            "visible": [
                {
                    "type": "repeat",
                    "text": "Do not share",
                    "direction": "horizontal"
                }
            ]
        }
    ]
}
requests.post("https://api.steg.ai/encode", headers=headers, body=json.dumps(body))
        

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
};
const body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_ID",
            "visible": [
                {
                    "type": "repeat",
                    "text": "Do not share",
                    "direction": "horizontal"
                }
            ]
        }
    ]
};
fetch("https://api.steg.ai/encode",
    method: "POST",
    headers: headers , 
    body: JSON.stringify(body)
)
        

curl --request POST "https://api.steg.ai/encode" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" \ 
--data '{"assets":[{"asset_id":"EXAMPLE_ASSET_ID","visible":[{"type":"repeat","text":"Do not share","direction":"horizontal"}]}]}'
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID",
  "data": [
      {
          "original_asset": "EXAMPLE_ASSET_ID",
          "source": "STEG",
          "watermarked_asset_id": "c20007c5-fe03-4db8-b394-c874d570cdab",
          "watermarked_path": "URL_TO_WATERMARKED_ASSET"
      }
  ]
}

async and batch encode

If more than one asset is provided for a batch request or the async flag is set to true, we will handle the request asynchronously. To handle asynchronous requests, we recommend using our webhooks API. To setup webhooks for handling batch encode requests, you should subscribe to the encode.success event.


If you are unable to use the webhooks, we provide an alternative approach based on polling. When we receive a batch encode request, we return a request_id. This request_id can be used with the status endpoint to check on the status of the batch encode. See the status endpoint for more information.

Response JSON Object

Attributes


request_id string
The unique identifier of the request. Used for status endpoint.

post /encode

import json
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
}
body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_ID",
            "forensic": [
                {
                    "data": {
                        "vendor": "Vendor A",
                        "use": "graphics only"
                    }
                }
            ]
        },
        {
            "url": "www.path_to_png_image.com",
            "mime_type": "image/png",
            "visible": [
                {
                    "type": "repeat",
                    "text": "Do not share",
                    "direction": "horizontal"
                }
            ]
        },
        "..."
    ]
}
requests.post("https://api.steg.ai/encode", headers=headers, body=json.dumps(body))
        

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
};
const body = {
    "assets": [
        {
            "asset_id": "EXAMPLE_ASSET_ID",
            "forensic": [
                {
                    "data": {
                        "vendor": "Vendor A",
                        "use": "graphics only"
                    }
                }
            ]
        },
        {
            "url": "www.path_to_png_image.com",
            "mime_type": "image/png",
            "visible": [
                {
                    "type": "repeat",
                    "text": "Do not share",
                    "direction": "horizontal"
                }
            ]
        },
        "..."
    ]
};
fetch("https://api.steg.ai/encode",
    method: "POST",
    headers: headers , 
    body: JSON.stringify(body)
)
        

curl --request POST "https://api.steg.ai/encode" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" \ 
--data '{"assets":[{"asset_id":"EXAMPLE_ASSET_ID","forensic":[{"data":{"vendor":"Vendor A","use":"graphics only"}}]},{"url":"www.path_to_png_image.com","mime_type":"image/png","visible":[{"type":"repeat","text":"Do not share","direction":"horizontal"}]},"..."]}'
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID"
}

Upload

generate a presigned URL

This endpoint generates a presigned URL for you to upload your asset.

Request Body

Parameters


name string Required
The filename of the asset.

content_type string Required
The asset's content type. See the available types here.

expiration integer
The duration of time (in seconds) that the presigned URL is valid. The default is 300 seconds. The max value is 43200 seconds.

Response JSON Object

Attributes


request_id string
The unique identifier of the request. Used for status endpoint.

data array[PresignedURL]
An array containing one PresignedURL object.

PresignedURL Object

Attributes


asset_id string
The unique identifier for the asset that will be uploaded.

post_to object
Contains the URL and form fields to make the POST request to upload a file.

timestamp_expires datetime
The date and time the presigned URL will expire. Format: YYYY-MM-DD HH:MM:SS

timestamp_created datetime
The date and time the presigned URL was created. Format: YYYY-MM-DD HH:MM:SS.

post /upload

import json
import requests

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

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
};
const body = {
    "name": "name_of_file",
    "content_type": "image/png"
};
fetch("https://api.steg.ai/upload",
    method: "POST",
    headers: headers , 
    body: JSON.stringify(body)
)
        

curl --request POST "https://api.steg.ai/upload" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" \ 
--data '{"name":"name_of_file","content_type":"image/png"}'
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID",
  "data": [
    {
      "asset_id": "EXAMPLE_ASSET_ID",
      "timestamp_created": "2024-03-10T17:06:48.823040",
      "timestamp_expires": "2024-03-10T17:11:48.823040",
      "post_to": {
        "url": "PRESIGNED_URL_HERE",
        "fields": "PRESIGNED_FORM_FIELDS_HERE"
      }
    }
  ]
}

upload file

After generating a presigned url, use the post_to attribute from the PresignedURL object to make a POST request to upload your file. Only one file can be uploaded per presigned URL.

Uploading a file to presigned URL

import requests

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

requests.post(url=PRESIGNED_URL_HERE, files=files, data=PRESIGNED_FORM_FIELDS_HERE)


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

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

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


curl --request POST "PRESIGNED_URL_HERE" \
--form 'PRESIGNED_FORM_FIELDS_HERE' \
--form 'file=@"/path/to/image"'

Usage

get usage of the api

This endpoint returns your history of usage of each Steg AI API endpoint. The order of returned items is chronologically from most recent to oldest. By default, each request will return a max of 25 items, but can be increased to up to 100. For requests where the response returns more than the max, we implement a pagination strategy. See our pagination section for details.

Query Strings

Parameters


start string
The start date to view the usage of. Format needs to be YYYY-MM-DD.

end string
The end date to view the usage of. Format needs to be YYYY-MM-DD.

next string
The key to retrieve the next set of items in the data array.

limit int
Number of items in the data array to return. Default is 25. Max value is 100.

Response JSON Object

Attributes


request_id string
The unique identifier of the request. Used for status endpoint.

data array[UsageRecord]
An array of UsageRecord objects.

next_key string
This value is used for pagination and is only included in the response when there are more items in a data array that can be retrieved. Include it in the next query param in a subsequent call to the endpoint to retrieve the next set of items in the data array.

UsageRecord Object

Attributes


endpoint string
The name of the endpoint.

status_code integer
The status code returned when the endpoint was called.

timestamp datetime
The date and time the endpoint was used. Format: YYYY-MM-DD HH:MM:SS.

asset_id nullable string
A unique identifier of the asset that was used for the endpoint. Only appears if the request was success.

get /usage

import requests

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

requests.get("https://api.steg.ai/usage", headers=headers)
        

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

fetch("https://api.steg.ai/usage",
    method: "GET",
    headers: headers 
)
        

curl --request GET "https://api.steg.ai/usage" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" 
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID",
  "data": [
      {
          "asset_id": "d051f164-b066-4702-8343-c61ba098ba63",
          "timestamp": "2024-03-10T16:54:24",
          "endpoint": "encode",
          "status_code": 200
      },
      {
          "asset_id": "e5c57510-d2e2-4cc8-afb4-b3ce1fa77b71",
          "timestamp": "2024-03-10T17:12:15",
          "endpoint": "encode",
          "status_code": 200
      },
      {
          "asset_id": null,
          "ts": "2024-03-10T117:27:58",
          "endpoint": "encode",
          "status_code": 400
      },
      . . .
  ],
  "next_key": "EXAMPLE_PAGE_KEY"
}

Webhooks

Webhooks are a way for one application to notify another about specific events or updates automatically. Instead of actively checking for changes, 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
encode.successTriggers after an encoding is finished.
encode.failureTriggers after an encoding fails.
decode.successTriggers after a decoding is finished.
decode.failureTriggers after a decoding fails.

receiving events

All webhook events received by your URL from Steg AI will have a timestamp and signature in the header: X-StegAI-Signature. This is used to verify that the request came from Steg AI. 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. This 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 this secret key into your system. Your URL must return a status code: 200; otherwise, we will retry sending the event.

Header

Parameters


t= timestamp
The timestamp of when the webhook event is sent.

s= string
The hashed signature of the webhook event.

Body

Parameters


event_type string
The type of event to which the webhook is subscribed. Possible values are here.

asset_id string
The unique identifier of the asset that triggered the webhook.

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

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

webhooks retry

If your URL does not return a 200 status code, we will retry sending the event using an exponential backoff policy. This policy increases the delay between each attempt we make to send the webhook event to your URL. After the initial failure, we will retry after 2, 4, 8, and 16 hours. If after the 4th retry attempt your URL still returns a non-200 status code, we will delete the webhook message and mark it as a failure.

get webhook events list

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

Response JSON Object

Attributes


request_id string
The unique identifier of the request. Used for status endpoint.

events array
The event types available to subscribe to.

get /webhook/events

import requests

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

requests.get("https://api.steg.ai/webhook/events", headers=headers)
        

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

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

curl --request GET "https://api.steg.ai/webhook/events" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" 
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID",
  "data": {
      "events": ["encode.success", "encode.failure", "decode.success", "decode.failure"]
  }
}

get webhook subscriptions

This endpoint returns all the webhooks you have subscribed to.

Response JSON Object

Attributes


request_id string
The unique identifier of the request. Used for status endpoint.

id string
A unique identifier of the webhook subscription.

event_type string
The type of event to which the webhook is subscribed. Possible values are here.

url string
The URL to which the webhook is sending POST requests.

get /webhook

import requests

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

requests.get("https://api.steg.ai/webhook", headers=headers)
        

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

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

curl --request GET "https://api.steg.ai/webhook" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" 
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID",
  "data": {
      "webhooks": [
          {
              "id": "54244b6a-87c2-4de5-87c6-ccf77ca390c2",
              "event_type": "encode.success",
              "url": "https://yourdomain.com/custom_endpoint"
          }
      ]
  }
}

create webhook subscription

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 to successfully create the webhook subscription.

Request Body

Parameters


event string Required
The event type to which you want to subscribe.

url string Required
The URL that you want the webhook to send POST requests to.

Response JSON Object

Attributes


request_id string
The unique identifier of the request. Used for status endpoint.

id string
A unique identifier of the webhook subscription.

event_type string
The type of event to which the webhook is subscribed. Possible values are here.

url string
The URL to which the webhook is sending POST requests.

post /webhook

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))
        

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)
)
        

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"}'
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID",
  "data": {
      "id": "54244b6a-87c2-4de5-87c6-ccf77ca390c2",
      "event_type": "encode.success",
      "url": "https://yourdomain.com/custom_endpoint"
  }
}

delete webhooks subscription

This endpoint deletes a webhook subscription.

Request Path

Parameters


id string Required
The unique identifier of the webhook you want to delete.

Response JSON Object

attributes


request_id string
The unique identifier of the request. Used for status endpoint.

delete /webhook/:id

import requests

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

requests.delete("https://api.steg.ai/webhook/:id", headers=headers)
        

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

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

curl --request DELETE "https://api.steg.ai/webhook/:id" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" 
        
response json object
{
  "request_id": "EXAMPLE_REQUEST_ID",
}

Asset

retrieve all assets

This endpoint returns all the assets and associated data that you have uploaded. The order of returned assets is based on their id. By default, each request will return a max of 25 items, but can be increased to up to 100. For requests where the response returns more than the max, we implement a pagination strategy. See our pagination section for details.

Query String

Parameters


next string
The key to retrieve the next set of items in the data array.

limit int
Number of items in the data array to return. Default is 25. Max value is 100.

Response JSON Object

attributes


request_id string
The unique identifier of the request. Used for status endpoint.

data array[StegAsset]
An array of StegAsset objects.

next_key string
This value is used for pagination and is only included in the response when there are more items in a data array that can be retrieved. Include it in the next query param in a subsequent call to the endpoint to retrieve the next set of items in the data array.

StegAsset Object

attributes


asset_id string
The unique identifier for the asset that was returned from the upload endpoint.

asset_type enum[string]
An enum that specifies the type of asset. Possible enum values are image, video, or pdf.

c2pa_path nullable string
A downloadable URL to the c2pa manifest of the asset.

content_type string
The asset's content type. See the available types here.

file_path string
A downloadable URL to the asset.

file_size integer
The file size of the asset in bytes.

is_watermarked boolean
Indicates whether the asset has been watermarked or not.

name string
The filename of the asset.

thumbnail string
A downloadable URL to the thumbnail version of the asset.

version integer
The current version of the asset.

original_asset nullable string
The asset_id of the InternalAsset or the url of the ExternalAsset that was watermarked.

source enum[string]
An enum indicating where the original_asset came from. Possible values are steg and external.

watermark_data nullable object
The key-value pairs associated with the asset.

get /asset

import requests

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

requests.get("https://api.steg.ai/asset", headers=headers)
        

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

fetch("https://api.steg.ai/asset",
    method: "GET",
    headers: headers 
)
        

curl --request GET "https://api.steg.ai/asset" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" 
        
response json object
{
    "request_id": "EXAMPLE_REQUEST_ID",
    "data": [
        {
            "asset_id": "3c9927b9-e7f0-446a-8be1-db607a372b0c",
            "asset_type": "image",
            "content_type": "image/png",
            "c2pa_path": "URL_TO_C2PA_MANIFEST",
            "file_path": "URL_TO_ASSET",
            "file_size": 55391,
            "is_watermarked": true,
            "name": "3c9927b9-e7f0-446a-8be1-db607a372b0c.png",
            "original_asset": null,
            "source": "steg",
            "thumbnail": "URL_TO_ASSET_THUMBNAIL",
            "version": 1,
            "watermark_data": {
                "key": "value"
            }
        },
        {
            "asset_id": "fdb0de3c-a70b-4ea1-97e0-39d07ff2e925",
            "asset_type": "image",
            "content_type": "image/png",
            "c2pa_path": null,
            "file_path": "URL_TO_ASSET",
            "file_size": 55391,
            "is_watermarked": false,
            "name": "example.png",
            "original_asset": null,
            "source": "steg",
            "thumbnail": "URL_TO_ASSET_THUMBNAIL",
            "version": 1,
            "watermark_data": null
        }
        . . .
    ],
    "next_key": "EXAMPLE_PAGE_KEY"
}

retrieve asset

This endpoint returns the data of a specific asset.

Path

Parameters


asset_id string Required
The unique identifier for the asset that is returned from the upload or encode endpoint.

Response JSON Object

attributes


request_id string
The unique identifier of the request. Used for status endpoint.

data array[StegAsset]
An array of the specified StegAsset object.

get /asset/:asset_id

import requests

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

requests.get("https://api.steg.ai/asset/:asset_id", headers=headers)
        

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

fetch("https://api.steg.ai/asset/:asset_id",
    method: "GET",
    headers: headers 
)
        

curl --request GET "https://api.steg.ai/asset/:asset_id" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" 
        
response json object
{
    "request_id": "EXAMPLE_REQUEST_ID",
    "data": [
        {
            "asset_id": "3c9927b9-e7f0-446a-8be1-db607a372b0c",
            "asset_type": "image",
            "content_type": "image/png",
            "c2pa_path": "URL_TO_C2PA_MANIFEST",
            "file_path": "URL_TO_ASSET",
            "file_size": 55391,
            "is_watermarked": true,
            "name": "3c9927b9-e7f0-446a-8be1-db607a372b0c.png",
            "original_asset": null,
            "source": "steg",
            "thumbnail": "URL_TO_ASSET_THUMBNAIL",
            "version": 1,
            "watermark_data": {
                "key": "value"
            }
        }
    ]
}

delete assets

This endpoint deletes a list of assets.

Request Body

Parameters


asset_id string Required
The unique identifier for the asset that is returned from the upload or encode endpoint.

Response JSON Object

attributes


request_id string
The unique identifier of the request. Used for status endpoint.

delete /asset

import json
import requests

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

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
};
const body = {
    "assets": [
        "EXAMPLE_MEDIA_ID"
    ]
};
fetch("https://api.steg.ai/asset",
    method: "DELETE",
    headers: headers , 
    body: JSON.stringify(body)
)
        

curl --request DELETE "https://api.steg.ai/asset" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" \ 
--data '{"assets":["EXAMPLE_MEDIA_ID"]}'
        
response json object
{
    "request_id": "EXAMPLE_REQUEST_ID",
}

delete asset

This endpoint delete an asset.

Path

Parameters


asset_id string Required
The unique identifier for the asset that is returned from the upload or encode endpoint.

Response JSON Object

attributes


request_id string
The unique identifier of the request. Used for status endpoint.

delete /asset/:asset_id

import requests

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

requests.delete("https://api.steg.ai/asset/:asset_id", headers=headers)
        

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

fetch("https://api.steg.ai/asset/:asset_id",
    method: "DELETE",
    headers: headers 
)
        

curl --request DELETE "https://api.steg.ai/asset/:asset_id" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" 
        
response json object
{
    "request_id": "EXAMPLE_REQUEST_ID",
}

update asset

This endpoint updates a specific asset. Any parameter in Request Body listed below can be updated.

Path

Parameters


asset_id string Required
The unique identifier for the asset that is returned from the upload or encode endpoint.

Request Body

Parameters


name string
The filename of the asset.

data object
Any custom data of key-value pairs to associate with the asset.

Response JSON Object

attributes


request_id string
The unique identifier of the request. Used for status endpoint.

data array[StegAsset]
An array of the newly updated StegAsset object.

patch /asset/:asset_id

import json
import requests

headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
}
body = {
    "name": "new_name.png",
    "data": {
        "new_key": "new_value"
    }
}
requests.patch("https://api.steg.ai/asset/:asset_id", headers=headers, body=json.dumps(body))
        

const headers = {
    "Content-Type": "application/json",
    "x-api-key": "api_key_here"
};
const body = {
    "name": "new_name.png",
    "data": {
        "new_key": "new_value"
    }
};
fetch("https://api.steg.ai/asset/:asset_id",
    method: "PATCH",
    headers: headers , 
    body: JSON.stringify(body)
)
        

curl --request PATCH "https://api.steg.ai/asset/:asset_id" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" \ 
--data '{"name":"new_name.png","data":{"new_key":"new_value"}}'
        
response json object
{
    "request_id": "EXAMPLE_REQUEST_ID",
    "data": [
        {
            "asset_id": "3c9927b9-e7f0-446a-8be1-db607a372b0c",
            "asset_type": "image",
            "content_type": "image/png",
            "c2pa_path": "URL_TO_C2PA_MANIFEST",
            "file_path": "URL_TO_ASSET",
            "file_size": 55391,
            "is_watermarked": true,
            "name": "new_name.png",
            "original_asset": null,
            "source": "steg",
            "thumbnail": "URL_TO_ASSET_THUMBNAIL",
            "version": 2,
            "watermark_data": {
                "new_key": "new_value"
            }
        }
    ]
}

Check Status

get status

This endpoint allows a user to get the status of a request.

Path

Parameters


request_id string Required
The unique identifier of a request that is returned from the endpoint.

Response JSON Object

attributes


request_id string
The unique identifier of the request. Used for status endpoint.

data array[statusRequest]
An array of a StatusRequest object.

StatusRequest Object

attributes


status enum[string]
An enum indicating the status of the request. Possible enum values: in progress, error, completed.

request_type string
The name of the endpoint of the request.

request_data nullable array
An array of objects based on the request. Not null when status is completed.

get /status/:request_id

import requests

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

requests.get("https://api.steg.ai/status/:request_id", headers=headers)
        

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

fetch("https://api.steg.ai/status/:request_id",
    method: "GET",
    headers: headers 
)
        

curl --request GET "https://api.steg.ai/status/:request_id" \
--header "Content-Type: application/json" \
--header "x-api-key: api_key_here" 
        
response json object for 'in progress' status
{
    "request_id": "EXAMPLE_REQUEST_ID",
    "data": [{
        "status": "in progress",
        "request_type": "encode",
        "request_data": null
    }]
}
response json object for 'completed' status
{
    "request_id": "EXAMPLE_REQUEST_ID",
    "data": [{
        "status": "completed",
        "request_type": "encode",
        "request_data": [
            {
                "original_asset": "EXAMPLE_ASSET_ID",
                "source": "STEG",
                "watermarked_asset_id": "c20007c5-fe03-4db8-b394-c874d570cdab",
                "watermarked_path": "URL_TO_WATERMARKED_ASSET"
            },
            ". . ."
        ]
    }]
}

Content Types

supported asset list

To generate a presigned url, the content_type parameter needs to be set to one of the following values:

Content Type

Value


application/pdf

image/bmp

image/gif

image/x-icon

image/jpeg

image/png

image/tiff

image/webp

video/mpeg

video/mp4

video/quicktime


How To Guides

This section describes the most common flows to support developers getting started with the Steg AI API.


how to forensic watermark an image

In this guide, we will show you how to apply a forensic watermark to an image of your choosing using python and the Steg AI API.

full code to forensic watermark an image
import json

import requests

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

headers = {
    "Content-Type": "application/json",
    "x-api-key": APIKEY
}
# Step 1: Generate presigned URL
payload = {
    "name": "unencoded_logo.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")[0].get("post_to")
asset_id = response.json().get("data")[0].get("asset_id")

# Step 2: Upload the image to the presigned URL
with open("unencoded_logo.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)

# Step 3: Start the process to encode the image
payload = {
    "assets": [{
        "asset_id": asset_id,
        "forensic": [{
            "data": {
                "message": "this is an example image that's been watermarked",
                "location": "New York, NY",
                "ip_address": "192.158.1.38"
            }
        }]
    }]
}
response = requests.post(f"{BASE_URL}/encode", headers=headers, data=json.dumps(payload))
watermarked_path = response.json().get("data")[0].get("watermarked_path")

# Step 4: Download the watermarked image
response = requests.get(url=watermarked_path)
with open("encoded_logo.png", 'wb') as f:
    f.write(response.content)


how to visible watermark an image

In this guide, we will show you how to apply a visible watermark to an image of your choosing using python and the Steg AI API. The visible watermark will say “Do not share” repeatedly across the image in the horizontal direction.

full code to visible watermark an image
import json

import requests

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

headers = {
    "Content-Type": "application/json",
    "x-api-key": APIKEY
}
# Step 1: Generate presigned URL
payload = {
    "name": "unencoded_logo.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")[0].get("post_to")
asset_id = response.json().get("data")[0].get("asset_id")

# Step 2: Upload the image to the presigned URL
with open("unencoded_logo.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)

# Step 3: Start the process to encode the image with a visible watermark
payload = {
    "assets": [{
        "asset_id": asset_id,
        "visible": [{
            "type": "repeat",
            "text": "Do not share",
            "direction": "horizontal"
        }]
    }]
}
response = requests.post(f"{BASE_URL}/encode", headers=headers, data=json.dumps(payload))
watermarked_path = response.json().get("data")[0].get("watermarked_path")

# Step 4: Download the watermarked image
response = requests.get(url=watermarked_path)
with open("encoded_logo.png", 'wb') as f:
    f.write(response.content)


how to decode an image

In this guide, we will show how to decode the watermarked image from How to Forensic Watermark an Image using python and the Steg AI API. When successfully decoded, the image will contain data with the following message: “this is an example image that’s been watermarked”.

full code to decode image
import json
import requests

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

headers = {
    "Content-Type": "application/json",
    "x-api-key": APIKEY
}
# Step 1: Generate presigned URL
payload = {
    "name": "encoded_logo.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")[0].get("post_to")
asset_id = response.json().get("data")[0].get("asset_id")

# Step 2: Upload the image to the presigned URL
# Using the watermarked image from "How to Forensic Watermark an Image"
with open("encoded_logo.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)

# Step 3: Start the process to decode the image
payload = {
    "assets": [{
        "asset_id": asset_id
    }]
}
response = requests.post(f"{BASE_URL}/decode", headers=headers, data=json.dumps(payload))

# Step 4: Retrieve the data of the decoded image
data_found = response.json().get("data")[0].get("data_found")
print(data_found.get("data"))


how to subscribe to a webhook event

In this guide, we will show how to subscribe to Steg AI webhooks using python and the Steg AI API.

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 are using Flask as an example server to handle the defined URL from the previous step. Be sure to save the secret key in your system. You must return the same header: X-Hook-Secret and status code: 200 in 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 systtem

            # 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
                asset_id = request_data.get("asset_id")
                headers = {
                    "Content-Type" : "application/json",
                    "x-api-key" : api_key
                }
                response = requests.get(f"https://api.steg.ai/asset/{asset_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)