NAV Navbar
cURL Python

Introduction

Welcome to the IMATAG API v3!

This API is intended for enterprise customers to register on-premises watermarked media and track their usage on the Internet or via PDF analysis.

Authentication

We use token authorization via HTTP header, to provide secure access to your account via our API. There is 3 ways to authenticate yourself.

API key

IMATAG uses API keys to allow access to the API. Your API key is available in your account settings on IMATAG. This is the simplest way to authenticate but it's also the less secure as your token will be the same ad vitam aeternam.

To authorize, use this code:

import requests

# with requests library, you can just pass the correct header with each request
headers = {"Authorization":"Token putyourapitokenhere"}
response = requests.get("api_endpoint_here", headers=headers)
# With shell, you can just pass the correct header with each request
curl "api_endpoint_here" \
  -H "Authorization: Token putyourapitokenhere"

Make sure to replace putyourapitokenhere with your API key.

IMATAG API expects the API key to be included in all requests to the server in the authorization header as follow:

Authorization: Token putyourapitokenhere

OAuth2

You can find the OAuth specification here https://www.oauth.com/. Imatag support OAuth authentication using client credential only. It is suitable for machine-to-machine authentication.

Create an application

Create an application

import requests

url = "https://app.imatag.com/api/v3/account/oauth/applications/"
response = requests.post(url, data={"name": "my_app"}, headers={"Authorization": "Token your_api_key"})
curl -X POST https://app.imatag.com/api/v3/account/oauth/applications/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Token your_api_key' \
-d '{"name":"my_app"}'

You'll get a response like this :

{
    "id": 42,
    "name": "your_app_name",
    "client_id": "your_client_id",
    "client_secret": "your_client_secret"
}

You will have to provide your api key that you can find in your account settings.

HTTP Request

POSThttps://imatag.com/api/v3/account/oauth/applications/

Request content

Attribute Required Description
name True The name of your application

Response description

Attribute Description
id Id of your application
name Name of your application
client_id Your client_id for this application
client_secret Your client_secret for this application

Get access token

Get access token

import base64
import requests

client_id = "your_client_id"
client_secret = "your_client_secret"
credentials = f"{client_id}:{client_secret}"
encoded_credentials = base64.b64encode(credentials.encode("utf-8")).decode("utf-8")
headers = {
    "Content-Type": "application/x-www-form-urlencoded",
    "Authorization": f"Basic {encoded_credentials}"
}
url = "https://imatag.com/o/token/"

response = requests.post(url, headers=headers, params={"grant_type": "client_credentials"})
curl -X POST "https://imatag.com/o/token/" \
    -H "Authorization: Basic your_encoded_credentials" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "grant_type=client_credentials"

You'll get a response like this :

{
  "access_token": "your_token",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "openid"
}

To get a token you need to encode client_id and client_secret separated by a colon as HTTP base authentication encoded in base64.

HTTP Request

POSThttps://imatag.com/o/token/

Request content

Attribute Required Value
grant_type True client_credentials

Response description

Attribute Description
access_token Your access token
expires_in Time of validity in seconds
token_type The type of token
scope The scope of the access token

Make API requests

The access token should be used as follows:

import requests

headers = {"Authorization": "Bearer your_access_token"}
response = requests.get("https://imatag.com/api/v3/endpoint/", headers=headers)
curl "https://imatag.com/api/v3/endpoint/" \
  -H "Authorization: Bearer your_access_token"

Now that you have your access_token, you need to use it as your credential. To do so, simply use it as a Bearer token. Note that the access token expires one hour after its creation. To get another one, simply follow again the get access token process

List applications

List applications

import requests

url = "https://app.imatag.com/api/v3/account/oauth/applications/"
response = requests.get(url, headers={"Content-Type": "application/json", "Authorization": "Bearer your_access_token"})
curl -X GET http://127.0.0.1:8000/api/v3/account/oauth/applications/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Token your_access_token'

You'll get a response like this :

{
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 1,
      "name": "my_app_1",
      "client_id": "client_id_1",
      "created": "2023-01-19T16:49:49.470412+01:00"
    },
    {
      "id": 2,
      "name": "my_app_2",
      "client_id": "client_id_2",
      "created": "2023-01-19T16:50:17.485791+01:00"
    }
  ]
}

You can list your applications. To do so, proceed as follows :

HTTP Request

GEThttps://imatag.com/api/v3/account/oauth/applications/

Response description

Attribute Description
next Next page link
previous Previous page link
results List of apps

Get applications

Get application detail

import requests

url = "https://app.imatag.com/api/v3/account/oauth/applications/app_id/"
response = requests.get(url, headers={"Content-Type": "application/json", "Authorization": "Bearer your_access_token"})
curl -X GET https://app.imatag.com/api/v3/account/oauth/applications/app_id/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Token your_access_token'

You'll get a response like this :

{
  "id": "app_id",
  "name": "my_app",
  "client_id": "client_id",
  "created": "2023-01-19T16:49:49.470412+01:00"
}

You can get an application detail. To do so, proceed as follows :

HTTP Request

GEThttps://imatag.com/api/v3/account/oauth/applications/app_id/

Application object

Attribute Description
id Application id
name Name of the application
client_id Client id of the application
created Date of creation

Delete an application

Delete an application

import requests

url = "https://app.imatag.com/api/v3/account/oauth/applications/app_id/"
response = requests.delete(url, headers={"Authorization": "Bearer your_access_token"})
curl -X DELETE https://app.imatag.com/api/v3/account/oauth/applications/app_id/ \
-H 'Authorization: Token your_access_token'

You'll get an empty body response with a 204 status code.

To revoke an application authorization you can delete it. To do so, proceed as follows :

HTTP Request

DELETEhttps://imatag.com/api/v3/account/oauth/applications/app_id/

Request IDs

Each API request has an associated request identifier. You can find this value in the response headers, under X-Request-Id. If you need to contact us about a specific request, providing the request identifier will ensure the fastest possible resolution.

Pagination

All endpoints which return collections of objects use pagination. All those endpoints return the following attributes in their response:

Attribute Description
count Total number of objects
next url of the next objects in the sequence (null if end is reached)
previous url of the previous objects in the sequence (null at the start)
<attr_name> list of paginated objects (current chunk)

To navigate the collection, you need to iteratively do GET requests at the url provided in the next attribute for each chunk of the collection.

By default, a page will contain 100 object at most. You can change that number by specifying page_size=X as query parameter in any url. The maximum number of objects per page allowed is 100.

Rate Limits

# Example response headers

HTTP/1.0 200 OK
Date: Tue, 04 Dec 2018 09:31:20 GMT
Server: WSGIServer/0.1 Python/2.7.9
X-RateLimit-Secondly: 10
X-RateLimit-Secondly-Remaining: 9
X-RateLimit-Daily: 50000
X-RateLimit-Daily-Remaining: 49996
...
# Example response headers

HTTP/1.0 200 OK
Date: Tue, 04 Dec 2018 09:31:20 GMT
Server: WSGIServer/0.1 Python/2.7.9
X-RateLimit-Secondly: 10
X-RateLimit-Secondly-Remaining: 9
X-RateLimit-Daily: 50000
X-RateLimit-Daily-Remaining: 49996
...
# Example error response headers

HTTP/1.0 429 Unknown Status Code
Date: Tue, 04 Dec 2018 09:44:48 GMT
X-RateLimit-Secondly: 10
X-RateLimit-Secondly-Remaining: 0
X-RateLimit-Daily: 50000
X-RateLimit-Daily-Remaining: 49932
Retry-After: 1
...
# Example error response headers

HTTP/1.0 429 Unknown Status Code
Date: Tue, 04 Dec 2018 09:44:48 GMT
X-RateLimit-Secondly: 10
X-RateLimit-Secondly-Remaining: 0
X-RateLimit-Daily: 50000
X-RateLimit-Daily-Remaining: 49932
Retry-After: 1
...

IMATAG has the following global limits in place for API requests:

Customers exceeding either of those limits will receive error responses with a 429 status code.

Each API request will include the following rate limit headers in the response.

When running into a limit, you'll get an error response with an additional header Retry-After to indicate how many seconds you must wait before making another call.

If you're running into the Secondly/Minutely/Hourly limit, you should throttle the requests that your app is making to stay under that limit. If you find you're still hitting the call limits, or the daily limit is too small for your needs, please contact us with as many details as possible about what APIs you're using, how you're using them, and which limit you're hitting.

Image formats

Our API is currently limited to some images format only:

To use images directly on endpoints that support simple upload, use the corresponding media type (content-type header) for each image format:

Image Format Media Type
JPEG image/jpeg
PNG image/png
GIF image/gif

Output formats

By default, responses data are returned as json. You can choose to specify the output format as query parameter ?format=<format>.

We currently support the following formats:

Status Codes / Errors

Errors returned by the API may have a response body in the following form:

{
    'status_code': <http status code>,
    'code': 'optional_error_code',
    'details': 'either human readable message about the error or a nested structure with more details',
    'errors': 'a list or errors details when multiple errors occurred'
}
{
    'status_code': <http status code>,
    'code': 'optional_error_code',
    'details': 'either human readable message about the error or a nested structure with more details',
    'errors': 'a list or errors details when multiple errors occurred'
}

IMATAG uses conventional HTTP response codes to indicate the success or failure of an API request.

In general:

List of status codes

Status Code Meaning
200 OK -- Everything worked as expected.
201 Created -- A new resource was created.
204 No Content -- The resource was properly deleted - or no content was available to be returned
--- ---
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your API key is wrong. See Authentication.
403 Forbidden -- You don't have enough permission to access the requested resource.
404 Not Found -- The resource could not be found.
405 Method Not Allowed -- You tried to access a resource with an invalid method.
406 Not Acceptable -- You requested a format that isn't json.
409 Conflict -- The request could not be completed due to a conflict with the current state of the target resource.
410 Gone -- The requested endpoint has been removed from our servers.
411 Length Required -- The body is empty or the Content-Length is missing in the request headers.
415 Unsupported Media Type -- The content of the request is not in a format supported by the endpoint.
422 Unprocessable entity -- The request has valid content type and its syntax is correct but we were unable to process the contained data.
429 Too Many Requests -- You're requesting too many resources! See Rate Limits.
--- ---
500 Internal Server Error -- We had a problem with our server. Try again later.
501 Not Implemented -- The requested endpoint is documented by not yet developped. It will be available in the future.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.
504 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.

Error handling recommendations

4XX errors

5XX errors and network errors

Retry after 1h (or more)

Watermarking Software

Depending on your service plan, you might have access to the IMATAG watermarking software. It is used to watermark your images before registering them on the API media endpoint. This enables you to have the fastest possible watermarking pipeline, as well as making your delivery process independent from any IMATAG API calls, ensuring the highest possible reliability.

Download

Go to your IMATAG account and scroll down to the "Software download" section.

Installation

No installation is needed. The software you downloaded is a binary which can be executed to watermark images directly. It has no dependencies.

Before execution, you will have to make sure that:

Software usage

Assuming your current directory contains lamark, public_key.derand input_image.jpg

import subprocess

subprocess.check_call(["lamark",
                       "input_image.jpg",
                       "output_image.jpg", "registration.lmk",
                       "public_key.der"])
./lamark input_image.jpg output_image.jpg registration.lmk public_key.der

The above should produce the following output

LAMARK image watermarking tool 2.3.4
Copyright 2015-2018 Lamark

This software is based in part on the work of the Independent JPEG Group
Using fdlibm Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.

And create output_image.jpg and registration.lmk in your current directory.

lamark [options] <input_image.jpg> <output_image.jpg> <registration.lmk> <public_key.der>

Parameters Description
<input_image.jpg> The full-resolution input image, in JPEG or PNG format
<output_image.jpg> The full-resolution output wartermarked image, in same format as input
<registration.lmk> The encrypted registration data that should be sent on the media endpoint
<public_key.der> The encryption key downloaded from your IMATAG account. Used to encrypt the registration file
options Description
-t Transactional watermarking

Output and exit codes

The software always outputs version and licence information on stderr

Advanced usage: Transactional watermarking

./lamark    input_image.jpg output_image_1.jpg registration_1.lmk public_key.der
./lamark -t input_image.jpg output_image_2.jpg registration_2.lmk public_key.der

The "Transactional watermarking" -t option can be used to limit storage and bandwidth usage if you watermark the same original image many times. The drawback is that it will make your scripts stateful and generally more complex.

It works like this: the first time you watermark an image, do not use the -t option and register the registration.lmk file. When you watermark the same image again, add the -t option. This will make the new registration.lmk file much smaller. You can register it as usual.

What happens is that the normal or in this case the first registration.lmk file contains a smaller version of your image which is used by our servers to identify your image (it is also used to generate thumbnails for the web interface). If you watermark the same image again, you don't need to send it again and the -t option allows you not to. To identify the original we compute a hash of its pixels and which is included in the registration.lmk file. When we register a transactional registration.lmk, we find the file which was already registered with the same hash and use that one. This means that if you haven't registered the first one or have modified it's content in any way since then, you will get an error when you try to register the transactional registration.lmk. Note that we look at the pixel data so if you modify only the metadata you should be OK.

Watermark detection information

Statistical significance

Throughout this API and IMATAG in general, images are said to be "watermarked" if the detection test result has a P-value lower than a fixed probability of error threshold (IMATAG communicates this threshold upon request to clients).

For security reasons, IMATAG does not normally provide the actual P-value of any given match and it is therefore not accessible via the API. If you have a legal reason that requires this p-value for a given query, please contact IMATAG and we will provide you the information.

Versioning

The versioning of the API is specified as part of the URI. For instance, in order to use v3 of the API the request URI should begin with /api/v3 followed by a specific endpoint.

https://imatag.com/api/v3/<endpoint>

Supported versions are:

API Version Documentation link
v1 (deprecated) v1
v2 (current) v2
v3 (development) v3

API Endpoints

Below is the list of all available endpoints & their full description: this is API (ツ) time!

Account

Account information

This endpoint allows you to check your account information and status.

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get(
    "https://imatag.com/api/v3/account/",
    headers=headers)
curl -X GET \
  https://imatag.com/api/v3/account/ \
  -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "username": "api.demo",
    "email": "support@imatag.com",
    "full_name": "api demo",
    "incidents": null,
    "image_count": 9,
    "image_quota": 50,
    "disk_quota": 13030726,
    "disk_usage": 2544966,
    "home": "api-demo", 
    "permissions":[],
    "quotas": {
        "uploaded_marks": 7,
        "uploaded_marks_limit": 50,
        "uploaded_images": 9,
        "uploaded_images_limit": 100,
        "active_paths_in_home": 12,
        "active_paths_in_home_limit": null,
        "paths_in_home": 12,
        "paths_in_home_limit": null,
        "user_paths": 12,
        "user_paths_limit": null
    }
}

HTTP Request

GEThttps://imatag.com/api/v3/account/

Response description

Attribute Description
username name of the account (cannot be modified)
full_name company name or first name & last name
email the email address used for login & contact
incidents current incidents on the account (null if none). See below for incidents description.
image_count current number of images owned by the user
image_quota maximum number of images based (null if no maximum)
disk_usage current disk usage of the user (in bytes)
disk_quota maximum disk usage (null if no maximum)
expires only in case of certain incidents, the date at which the account will be deleted
home the home directory of the user
quota detailed quota
permissions list of allowed permissions for the current account

incidents

description of the incidents

Value Description
null no incident
free trial expired the user subscribed to a free trial and it has expired ("expires" will be set)
payment overdue the last payment of the user has not come through ("expires" will be set)
quota exceeded the current number of images owned by the user exceeds their quota or their disk usage exceed their disk quota

Account settings

This endpoint allows you to check your account settings.

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get(
    "https://imatag.com/api/v3/account/settings/",
    headers=headers)
curl -X GET \
  https://imatag.com/api/v3/account/settings/ \
  -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "lang": "en",
    "notifications": {
        "notify_upload": true,
        "notify_pdf": false,
        "notify_web": false,
        "notify_download": false,
        "notify_favorite": false,
        "notify_newsletter": true,
        "notify_offers": false,
        "notify_pdf_daily": false,
        "notify_pdf_weekly": false,
        "notify_match_url_daily": false,
        "notify_match_url_weekly": false,
        "notify_match_site_daily": false,
        "notify_match_site_weekly": false
    }
}

HTTP Request

GET|POSThttps://imatag.com/api/v3/account/settings/

Response description

Attribute Description
lang language (fr, en)
notifications dictionary of key:value

Download software and key

There is an endpoint that allow you to list the latest software version's binaries available.

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get(
    "https://imatag.com/api/v3/account/download/",
    headers=headers)
curl -X GET \
  https://imatag.com/api/v3/account/download/ \
  -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:


{
    "version": "X.Y.Z",
    "key": {
        "public_key.der": "/api/v3/account/download/key/"
    },
    "software": {
        "lamark": "/api/v3/account/download/software/X.Y.Z/lamark",
        "lamark.exe": "/api/v3/account/download/software/X.Y.Z/lamark.exe"
    }
}

HTTP Request

GEThttps://imatag.com/api/v3/account/download/

Response description

Attribute Description
version the name of the current version
key a dict of each key you can have
key.<name> the url to call (GET) to get your encription key (ie: public_key.der)
software a dict where each key represent a software available
software.<name> the url to call (GET) to download this specific software

Aggregations

This endpoint allows you to view aggregated information about matches.

There are different endpoints that can be used to get these aggregations.

List all endpoints

This endpoint allows to retrieve the list of aggregations endpoints available. Please note that any endpoint listed can be renamed, removed or added at any time.

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get("https://imatag.com/api/v3/aggregations/", headers=headers)
curl -X GET \
  https://imatag.com/api/v3/aggregations/ \
  -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

[
    {
        "url": "/api/v3/aggregations/group-path/",
        "name": "group-path"
    },
    {
        "url": "/api/v3/aggregations/group-site-path/",
        "name": "group-site-path"
    },
    {
        "url": "/api/v3/aggregations/group-site-path-pageurl/",
        "name": "group-site-path-pageurl"
    }
]

HTTP Request

GEThttps://imatag.com/api/v3/aggregations/

Response description

The response is a list, where each element is a dict containing the name and url of an aggregation.

Access to aggregation data

You can access to a specific aggregation, using any of the endpoints previously listed.

HTTP Request

GEThttps://imatag.com/api/v3/aggregations/<aggregation>/

URL Parameters

Parameter Required Description
aggregation true The name of the specific aggregation to query

As a reminder, the list of aggregation names can be retrieved using the list all endpoints.

Query Parameters

You can filter the response using query parameters with any allowed field as:

Parameter Description
<field>=... The field value is equal to the value
!<field>=... The field value is different from the value
<field>__isnull=... The field value is null
<field>__startswith=... The field value starts with the value
<field>__in=... The field value is within the comma separated list
<field>__gt=... The field value is greather than the value
<field>__lt=... The field value is lower than the value
<field>__gte=... or <field>>=... The field value is greater than or equal to the value
<field>__lte=... or <field><=... The field value is lower than or equal to the value

You can also export the data in csv format, in addition of the default output formats supported. To do so, you have to specify format=csv as a query parameter.

Due to format limitation, data can be slightly different (e.g. there is no list nor sub object in a csv format).

Response description

The response is a dict with pagination that contains a list of objects. The content of the response will be different for each aggregation endpoint. All aggregations will contain different data, but some are shared with all of them:

Field type can be used in query filter description
_id String yes unique identifier of the object
_version Integer no version of the object (number of modifications)
group Integer yes owner
type Enum yes 0: unknown
1: aggregation by video
2: aggregation by image
3: aggregation by crawler
4: aggregation by site
created Date yes date of creation of the object
updated Date yes date of the last update of the object
export Boolean yes indicate whether the object can be exported in csv format
deleted Boolean no should always be false
tags List of string yes tag that you can add to the object

Access to a single aggregation object

This endpoint provides access to a specific aggregation object, from its unique identifier.

Endpoint

GEThttps://imatag.com/api/v3/aggregations/<aggregation>/<_id>/

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get(
    "https://imatag.com/api/v3/aggregations/<aggregation>/<_id>/",
    headers=headers)
curl -X GET \
https://imatag.com/api/v3/aggregations/<aggregation>/<_id>/ \
-H "Authorization: Token <your api token>"

URL Parameters

Parameter Required Description
aggregation true The name of the specific aggregation to query
_id true The unique identifier of the aggration object

Response description

The content of the response is the same as in the list of object, but the response contain only one object.

Modify the object

To modify the object, you can use the PATCH method to change the value of some fields.

PATCHhttps://imatag.com/api/v3/aggregations/<aggregation>/<_id>/

import requests

headers = {
    "Authorization": "Token <your api token>",
}
data = {
    "tags": ["tag1", "tag2"],
    "export": False
}
response = requests.patch(
    "https://imatag.com/api/v3/aggregations/<aggregation>/<_id>/",
    json=data, headers=headers)
curl -X PATCH \
https://imatag.com/api/v3/aggregations/<aggregation>/<_id>/ \
-H "Content-Type: application/json" \
-H "Authorization: Token <your api token> \
--data '{"tags": ["tag1", "tag2"], "export": false}'

Request content

Attribute Required Description
export false Flag for allowing the csv export of the aggregation data
tags false List of tags of the aggregation object

Access to a single field of an object

This endpoint provides access to a specific field object (or to modify it). You'll need the _id of the object and the name of the field. You can also access elements in a list by index: field.<index> (e.g. tags.0)

Endpoint

GEThttps://imatag.com/api/v3/aggregations/<aggregation>/<_id>/<field>/

import requests

headers = {
    "Authorization": "Token <your api token>",
}

response = requests.get(
    "https://imatag.com/api/v3/aggregations/<aggregation>/<_id>/<field>/",
    headers=headers)
curl -X GET \
https://imatag.com/api/v3/aggregations/<aggregation>/<_id>/<field>/ \
-H "Authorization: Token <your api token>"

URL Parameters

Parameter Required Description
aggregation true The name of the specific aggregation to query
_id true The unique identifier of the aggration object
field true The name of the field to access; use field.` notation for accessing an item within a list.

Response description

The content of the response is the value of the field.

Modify the field value

import requests

headers = {
    "Authorization": "Token <your api token>",
}
data = {
    "content": ["tag1", "tag2"]

}
response = requests.put(
    "https://imatag.com/api/v3/aggregations/<aggregation>/<_id>/tags/",
    json=data, headers=headers)
curl -X PUT \
https://imatag.com/api/v3/aggregations/<aggregation>/<_id>/tags/ \
-H "Content-Type: application/json" \
-H "Authorization: Token <your api token>" \
--data '{"content": ["tag1", "tag2"]}'

To modify a field value, you have two options:

The content of the request must be JSON with following attributes:

Attribute Required Description
content true The new value of the field

Remove a field value

import requests

headers = {
    "Authorization": "Token <your api token>",
}

response = requests.delete(
    "https://imatag.com/api/v3/aggregations/<aggregation>/<_id>/tags.0/",
    headers=headers)
curl -X DELETE \
https://imatag.com/api/v3/aggregations/<aggregation>/<_id>/tags.0/ \
-H "Authorization: Token <your api token>"

This endpoint allows removal of:

DELETEhttps://imatag.com/api/v3/aggregations/<aggregation>/<_id>/<field>/:

Crawling

The crawling API controls web crawling specific web sites.

Crawling Session

A crawling session groups crawls of a website and defines the common parameters of those crawls. The first crawl is initiated (seeded) on the start_urls of the session. Links to pages internal to the domain are then added recursively to the list of pages to visit. Links to images are stored and visually matched to your media if the search option is enabled. Subsequent crawls start from the state of the latest crawl in the session and continue the crawling in a recursive manner.

Crawling Session Object

Attribute Description
url The URL of the session
id The unique identifier of the session
ctime Starting date of the session
mtime Modification date of the session (date of latest crawl)
stime Starting date of the last crawl
state State of the crawl (pending, running, failed, done or paused)
cycle_count Number of crawls performed on this session
crawl_delay Maximum duration of each crawl
search Whether to search for matches in your media
download_delay Delay between successive requests to the same domain
download_timeout Time to wait before assuming the connection timed out
start_urls List of urls the session was initiated on
batches URL of the list of crawling batches associated with the session (see Crawling Batch Object)

List all available sessions

HTTP Request

GEThttps://imatag.com/api/v3/crawling/sessions/

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get("https://imatag.com/api/v3/crawling/sessions/", headers=headers)
curl https://imatag.com/api/v3/crawling/sessions/ \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
   "results" : [
      {
         "ctime" : "2018-08-09T12:19:57.849603+02:00",
         "download_timeout" : 15,
         "url" : "https://imatag.com/api/v3/crawling/sessions/1/",
         "stime" : "2018-08-09T12:19:57.849603+02:00",
         "mtime" : "2018-08-21T12:01:06.401858+02:00",
         "id" : 1,
         "download_delay" : 0.1,
         "search" : true,
         "batches" : "https://imatag.com/api/v3/crawling/sessions/1/batches/",
         "crawl_delay" : 300,
         "cycle_count" : 1,
         "start_urls" : [
            "https://imatag.com/"
         ]
      }
   ],
   "previous" : null,
   "next" : null
}

Query Parameters

Parameter Default Description
ctime null If set, only results found on that exact date on the ctime field (or exact date & time) will be shown. This cannot be combined with other date lookups on the same field (gt, lt, etc.)
ctime_lte null If set, only results found on that date or earlier on the ctime field will be shown
ctime_gte null If set, only results found on that date or later on the ctime field will be shown
ctime_lt null If set, only results found earlier than that date on the ctime field will be shown
ctime_gt null If set, only results found later than that date on the ctime field will be shown

Response description

Attribute Description
next url of the next sessions in the sequence (null if end is reached)
previous url of the previous sessions in the sequence (null at the start)
results list of Crawling Session objects (see Crawling Session object)

Get a session

This endpoint retrieves information about a specific crawling session.

HTTP Request

GEThttps://imatag.com/api/v3/crawling/sessions/<session_id>/

import requests

headers = {
    'Authorization': 'Token <your api token>',
}
response = requests.get('https://imatag.com/api/v3/crawling/sessions/1/',
                        headers=headers)
curl https://imatag.com/api/v3/crawling/sessions/1/ \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
   "id" : 1,
   "batches" : "https://imatag.com/api/v3/crawling/sessions/1/batches/",
   "url" : "https://imatag.com/api/v3/crawling/sessions/1/",
   "mtime" : "2018-08-21T12:01:06.401858+02:00",
   "download_timeout" : 15,
   "start_urls" : [
      "https://imatag.com/"
   ],
   "stime" : "2018-08-09T12:19:57.849603+02:00",
   "ctime" : "2018-08-09T12:19:57.849603+02:00",
   "download_delay" : 0.1,
   "search" : true,
   "cycle_count" : 1,
   "crawl_delay" : 300
}

URL Parameters

Parameter Required Description
session_id true The unique id of the session to retrieve information on.

Response description

See Crawling Session object

Create a new session

HTTP Request

POSThttps://imatag.com/api/v3/crawling/sessions/

import requests

headers = {
    'Authorization': 'Token <your api token>',
}
response = requests.post('https://imatag.com/api/v3/crawling/sessions/',
    json={'url': 'http://imatag.com' }, headers=headers)
curl -X POST \
   https://imatag.com/api/v2/crawling/sessions/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Token <your api token>" \
  --data '{"url": "http://imatag.com"}'

The above command returns JSON structured like this:

{
   "mtime" : "2018-08-21T12:01:06.401858+02:00",
   "crawl_delay" : 300,
   "cycle_count" : 1,
   "download_timeout" : 15,
   "url" : "https://imatag.com/api/v3/crawling/sessions/1/",
   "ctime" : "2018-08-09T12:19:57.849603+02:00",
   "stime":"2018-08-09T12:19:57.849603+02:00"
   "id" : 1,
   "start_urls" : [
      "https://imatag.com/pour-entreprise/"
   ],
   "download_delay" : 1,
   "batches" : "https://imatag.com/api/v3/crawling/sessions/1/batches/",
   "search" : true
}

Request content

The content of the request must be JSON with following attributes:

Attribute Required Description
url true The URL to start crawling from.

Response description

See Crawling Session object

Delete an existing session

HTTP Request

DELETEhttps://imatag.com/api/v3/crawling/sessions/<session_id>/

URL Parameters

Parameter Required Description
session_id true The unique id of the session to delete.
import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.delete("https://imatag.com/api/v3/crawling/sessions/1/",
                           headers=headers)
curl -X DELETE \
  https://imatag.com/api/v3/crawling/sessions/1/ \
 -H "Authorization: Token <your api token>"

Crawling Batch

A crawling batch stores information gathered during a crawl. Each time a crawl is run, a new crawling batch object is created at the end of it.

Crawling Batch Object

Attribute Description
url The URL of the crawling batch
id The unique identifier of the crawling batch
ctime Starting time at which the batch was created (end of crawl)
session A link to the crawling session associated with this batch (see Crawling Session object)
images Dict of information on the images found in the crawl, detailled below
images.count Number of images found in the crawl
images.log URL to download the list of images found during the crawl, in gzipped CSV format (optional)
images.tar URL to download the images found during the crawl, in TAR format (optional)
videos Dict of information on the videos found in the crawl, detailled below
videos.count Number of videos found in the crawl
videos.log URL to download the list of videos found during the crawl, in gzipped CSV format (optional)
documents Dict of information on the documents found in the crawl, detailled below
documents.count Number of documents found in the crawl
documents.log URL to download the list of documents found during the crawl, in gzipped CSV format (optional)
pages Dict of information on the pages found in the crawl, detailled below
pages.count Number of pages found in the crawl
pages.log URL to download the list of pages found during the crawl, in gzipped CSV format (optional)
pages.warc URL to download the requests and responses corresponding to pages found during the crawl, in gzipped WARC format (optional)
crawl_cycle session's cycle_count value at the time the batch was made (crawl number)

List the batches of a session

HTTP Request

GEThttps://imatag.com/api/v3/crawling/sessions/<session_id>/batches/

URL Parameters

Parameter Required Description
session_id true The unique id of the session to retrieve batches for.
import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get("https://imatag.com/api/v3/crawling/sessions/1/batches/", headers=headers)
curl https://imatag.com/api/v3/crawling/sessions/1/batches/ \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
   "results" : [
      {
         "pages" : {
            "log" : "https://static4.imatag.com/54688,17b90549bdefbf86",
            "count" : 213,
            "warc" : "https://static2.imatag.com/54666,17b9054be3fb1b12"
         },
         "session" : "https://imatag.com/api/v3/crawling/sessions/1/",
         "ctime" : "2018-08-21T12:04:25.660571+02:00",
         "images" : {
            "count" : 1092,
            "log" : "https://static4.imatag.com/54679,17b90530f4c665e4"
         },
         "crawl_cycle" : 1,
         "id" : 7154,
         "url" : "https://imatag.com/api/v3/crawling/batches/7154/"
      },
      ...
   ],
   "next" : null,
   "previous" : null
}

Query Parameters

Parameter Default Description
ctime null If set, only results found on that exact date on the ctime field (or exact date & time) will be shown. This cannot be combined with other date lookups on the same field (gt, lt, etc.)
ctime_lte null If set, only results found on that date or earlier on the ctime field will be shown
ctime_gte null If set, only results found on that date or later on the ctime field will be shown
ctime_lt null If set, only results found earlier than that date on the ctime field will be shown
ctime_gt null If set, only results found later than that date on the ctime field will be shown

Response description

Attribute Description
next url of the next batches in the sequence (null if end is reached)
previous url of the previous batches in the sequence (null at the start)
results list of Crawling Batch objects (see Crawling Batch object)

List all available batches

HTTP Request

GEThttps://imatag.com/api/v3/crawling/batches/

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get("https://imatag.com/api/v3/crawling/batches/", headers=headers)
curl https://imatag.com/api/v3/crawling/batches/ \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
   "next" : null,
   "results" : [
      {
         "ctime" : "2018-08-13T15:51:23.186005+02:00",
         "session" : "https://imatag.com/api/v3/crawling/sessions/1/",
         "url" : "https://imatag.com/api/v3/crawling/batches/13/",
         "pages" : {
            "count" : 539,
            "warc" : "https://static3.imatag.com/54661,1729c1e94282b9aa",
            "log" : "https://static4.imatag.com/54686,1729c1e74e629d47"
         },
         "id" : 13,
         "crawl_cycle" : 1,
         "images" : {
            "count" : 2647,
            "log" : "https://static1.imatag.com/54682,1729c13dd6694192",
            "tar" : "https://static2.imatag.com/54662,1729c184b181ac39"
         }
      }
   ],
   "previous" : null
}

Query Parameters

Parameter Default Description
ctime null If set, only results found on that exact date on the ctime field (or exact date & time) will be shown. This cannot be combined with other date lookups on the same field (gt, lt, etc.)
ctime_lte null If set, only results found on that date or earlier on the ctime field will be shown
ctime_gte null If set, only results found on that date or later on the ctime field will be shown
ctime_lt null If set, only results found earlier than that date on the ctime field will be shown
ctime_gt null If set, only results found later than that date on the ctime field will be shown

Response description

Attribute Description
next url of the next batches in the sequence (null if end is reached)
previous url of the previous batches in the sequence (null at the start)
results list of Crawling Batch objects (see Crawling Batch object)

Get a batch

import requests

headers = {
    'Authorization': 'Token <your api token>',
}
response = requests.get('https://imatag.com/api/v3/crawling/batches/13/',
                        headers=headers)
curl https://imatag.com/api/v3/crawling/batches/13/ \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
   "id" : 13,
   "crawl_cycle" : 1,
   "pages" : {
      "log" : "https://static1.imatag.com/54686,1729c1e74e629d47",
      "warc" : "https://static4.imatag.com/54661,1729c1e94282b9aa",
      "count" : 539
   },
   "session" : "https://imatag.com/api/v3/crawling/sessions/1/",
   "images" : {
      "log" : "https://static1.imatag.com/54682,1729c13dd6694192",
      "count" : 2647
   },
   "url" : "https://imatag.com/api/v3/crawling/batches/13/",
   "ctime" : "2018-08-13T15:51:23.186005+02:00"
}

This endpoint retrieves information about a specific crawling batch.

HTTP Request

GEThttps://imatag.com/api/v3/crawling/batches/<batch_id>/

URL Parameters

Parameter Required Description
batch_id true The unique id of the batch to retrieve information on.

Response description

See Crawling Batch object

Domains

Domain object

The representation of a domain is fairly simple

Attribute Description
url domain name with extention (eg imatag.com); protocol is not necessary.

Domains blacklist

This endpoint /api/v3/domains/blacklist/ allows to manage a blacklist of web domains.

Matches recorded on blacklisted domains will be ignored (filtered out).

Add a domain to the blacklist

Add a domain to the blacklist:

import requests

headers = {
    "Authorization": "Token <your api token>",
}
data = {
    "url": "imatag.com"
}
response = requests.post(
    "https://imatag.com/api/v3/domains/blacklist/",
    json=data, headers=headers)

curl -X POST \
https://imatag.com/api/v3/domains/blacklist/ \
-H "Authorization: Token <your api token>" \
-H "Content-Type: application/json" \
--data '{"url": "imatag.com"}'

This endpoint allows to add a new domain to the blacklist

HTTP Request

POSThttps://imatag.com/api/v3/domains/blacklist/

Request content

The content of the request must be a valid domain description:

Attribute Required Description
url true domain name with extension

Response description

If the request is successful, the response is the newly blacklisted domain

Get all domains from the blacklist

Get all domains from the blacklist:

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get(
    "https://imatag.com/api/v3/domains/blacklist/",
    headers=headers)
curl -X GET \
https://imatag.com/api/v3/domains/blacklist/ \
-H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "next": null,
    "previous": null,
    "results": [
        {
            "url": "imatag.com"
        }
    ]
}

This endpoint allows to retrieve all domains that are registered in the blacklist

HTTP Request

GEThttps://imatag.com/api/v3/domains/blacklist/

Response description

Attribute Description
next not used yet; pagination is not enabled on this endpoint
previous not used yet; pagination is not enabled on this endpoint
results list of blacklisted domain objects

Removes a domain from the blacklist

Removes a domain from the blacklist:

import json
import requests

headers = {
    "Authorization": "Token <your api token>",
    'Content-Type': 'application/json',
}
data = {
    "url": "imatag.com"
}
response = requests.delete(
    "https://imatag.com/api/v3/domains/blacklist/",
    data=json.dumps(data), headers=headers)
curl -X DELETE \
https://imatag.com/api/v3/domains/blacklist/ \
-H "Authorization: Token <your api token>" \
-H "Content-Type: application/json" \
--data '{"url": "imatag.com"}'

This endpoint allows to remove a domain from the blacklist

HTTP Request

DELETEhttps://imatag.com/api/v3/domains/blacklist/

Request content

The content of the request must be a valid domain description:

Attribute Required Description
url true domain name with extension

Matches

Matches carry information on a matched image for a given query. The matched image is described by the Image object, which may refer to either an image registered on IMATAG or an image from the Web. Match information depend also on the source of the query, which may be images from the Web, documents from Press releases, or images and documents submitted via the Search API.

Web Matches

This endpoint lists all web matches found (similar and watermarked) on the Internet by our crawlers.

HTTP Request

GEThttps://imatag.com/api/v3/matches/web/

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get("https://imatag.com/api/v3/matches/web/", params={
    'watermarked': True, 'date': '2018-08-02'},
                        headers=headers)

response = requests.get("https://imatag.com/api/v3/matches/web/", params={
    'watermarked': True, 'date_gt': '2018-08-01', 'date_lte': '2018-08-02T12:45:00Z'},
    headers=headers)
curl 'https://imatag.com/api/v3/matches/web/?watermarked=true&date=2018-08-02' \
 -H "Authorization: Token <your api token>"

curl 'https://imatag.com/api/v3/matches/web/?watermarked=true&date_gt=2018-08-01&date_lte=2018-08-02T12:45:00Z' \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "count": 36858,
    "next": "https://imatag.com/api/v3/matches/web/?cursor=cD0xNTczNTgwNTgyNzQ5JmM9MzY4NTg%3D",
    "previous": null,
    "results": [
        {
            "id": 190113962,
            "url": "https://imatag.com/api/v3/matches/image/190113962/",
            "created": "2019-11-13T13:59:09.665391Z",
            "type": "web",
            "watermarked": false,
            "query_url": "http://p-umc.com/wp-content/uploads/slz-live-setting/boxed-bg-img-03.jpg",
            "query_page_url": "http://p-umc.com/sermon/the-invitation-is-to-all-a-wesley-hymn-devotion-for-lent/",
            "session_id": 5,
            "query_format": "jpeg",
            "query_width": 833,
            "query_height": 500,
            "image": {
                "type": "registered",
                "url": "https://static1.imatag.com/54578,15ec695538df826a",
                "width": 1280,
                "height": 853,
                "format": "jpeg",
                "thumbnail": "https://static1.imatag.com/206837,8110da3066effc82",
                "credit": null,
                "media_path": "api.demo/images/new-york/nyc-taxis.jpeg",
                "media_url": "https://imatag.com/api/v3/media/api.demo/images/new-york/nyc-taxis.jpeg",
                "metadata": {
                     "user.demo_key": "this is the value"
                }
            },
          "domain": "p-umc.com"
        },
        "..."
    ]
}

Query Parameters

Parameter Default Description
watermarked null If set to true, only watermarked results will be shown; if set to false, only non-watermarked results will be shown
exclusive null If set to true, only exclusive results will be shown; if set to false, only non-exclusive results will be shown
date null If set, only results found on that exact date (or exact date & time) will be shown. This cannot be combined with other date lookups (gt, lt, etc.)
date_lte null If set, only results found on that date or earlier will be shown
date_gte null If set, only results found on that date or later will be shown
date_lt null If set, only results found earlier than that date will be shown
date_gt null If set, only results found later than that date will be shown
blacklist null If set to true, only results from domains that are not in the blacklist will be returned (ie results for blacklisted domains are filtered out)
session_id null If set, only results originating from this Crawling Session id will be shown

Response description

Attribute Description
count Total number of matches
next url of the next matches in the sequence (null if end is reached)
previous url of the previous matches in the sequence (null at the start)
results list of web match objects (see Web Match object)

Web Match Object

Attribute Description
url The URL of this match (direct link)
created The date of creation of the match (ISO8601)
type The type of match (always "web")
watermarked Whether the watermark was found* (boolean)
exclusive If specified, whether the match is recorded for an exclusive image (optional boolean); at the time of the record
query_url The original URL of the query media
query_width The width of the query media
query_height The height of the query media
query_page_url The original URL of the page where the media was found
paths The list of corresponding media objects in your account (see Media object)
session_id ID of the from this Crawling Session that generated this match
domain Full domain of the query matched

Additionally, image matches have these extra fields:

Attribute Description
query_format format of the query image (e.g. jpeg or png)
image The image object (see Image object) matched with the query

Additionally, video matches have these extra fields:

Attribute Description
video The video object (see Video object) matched with the query
query_video_start_time start time in seconds of the match in the query video
query_video_end_time end time in seconds of the match in the query video
query_video_match_duration duration in seconds of the match in the query video
matched_video_start_time start time in seconds of the match in the matched video
matched_video_end_time end time in seconds of the match in the matched video
matched_video_match_duration duration in seconds of the match in the matched video

Press Matches

This endpoint lists all matches found in the press.

HTTP Request

GEThttps://imatag.com/api/v3/matches/press/

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get("https://imatag.com/api/v3/matches/press/", headers=headers)
curl https://imatag.com/api/v3/matches/press/ \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": "94457659",
            "url": "https://imatag.com/api/v3/matches/images/94457659/",
            "created": "2018-08-03T12:35:23.371022Z",
            "type": "press",
            "watermarked": true,
            "issue": {},
            "page_number": 1,
            "image": {
                "type": "registered",
                "url": "https://static2.imatag.com/54580,15ec6954eac4981b",
                "width": 1280,
                "height": 904,
                "thumbnail": "https://static3.imatag.com/211697,70014e5e3e082b02",
                "credit": null,
                "media_url": "https://imatag.com/api/v3/media/api.demo/images/new-york/brooklyn-bridge.jpeg"
            }
        }
    ]
}

Query Parameters

Parameter Default Description
watermarked null If set to true, only watermarked results will be shown, if set to false, only non-watermarked results will be shown
date null If set, only results found on that exact date (or exact date & time) will be shown. This cannot be combined with other date lookups (gt, lt, etc.)
date_lte null If set, only results found on that date or earlier will be shown
date_gte null If set, only results found on that date or later will be shown
date_lt null If set, only results found earlier than that date will be shown
date_gt null If set, only results found later than that date will be shown

Response description

Attribute Description
count Total number of matches
next url of the next matches in the sequence (null if end is reached)
previous url of the previous matches in the sequence (null at the start)
results list of press match objects (see Press Match object) sorted by match date, newest first

Press Match Object

Attribute Description
url The URL of this match (direct link)
created The date of creation of the match (ISO8601)
type The type of match (always "press")
watermarked Whether the watermark was found* or not (boolean)
issue Press issue where the media was found (see Press Issue object)
page_number Page of the issue where the image was found
paths The list of corresponding media objects in your account (see Media object)
image The image object (see Image object) matched with the query

Press Issue Object

Attribute Description
name Name of the publication
date Date of the publication (ISO8601, date only)

Credit Matches

This endpoint lists all matches found by matching your credit line(s).

HTTP Request

GEThttps://imatag.com/api/v3/matches/credit/

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get("https://imatag.com/api/v3/matches/credit/", headers=headers)
curl https://imatag.com/api/v3/matches/credit/ \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
      {
         "id": "95998502",
         "url" : "https://imatag.com/api/v3/matches/credit/95998502/",
         "page_url" : "https://imatag.com/portfolio/secretan/sets/f9ea5e942684421eaefcf2967290a2a9/",
         "credit" : "© Thierry Secretan - DSCF2144.jpg - protected by IMATAG",
         "type" : "credit",
         "created" : "2018-01-23T16:39:31.569700Z",
         "image_url" : "http://static2.imatag.com/53538/090ddbea3e6aa622/2af10e0b4b84ee7313552e6e9bc9fa37-thierry-secretan-dscf2144jpg.jpg"
      },
      ...
    ]
}

Query Parameters

Parameter Default Description
date null If set, only results found on that exact date (or exact date & time) will be shown. This cannot be combined with other date lookups (gt, lt, etc.)
date_lte null If set, only results found on that date or earlier will be shown
date_gte null If set, only results found on that date or later will be shown
date_lt null If set, only results found earlier than that date will be shown
date_gt null If set, only results found later than that date will be shown
blacklist null If set to true, only results from domains that are not in the blacklist will be returned (ie results for blacklisted domains are filtered out)

Response description

Attribute Description
count Total number of matches
next url of the next matches in the sequence (null if end is reached)
previous url of the previous matches in the sequence (null at the start)
results list of press match objects (see Text Match object) sorted by match date, newest first

Text Match Object

Attribute Description
url The URL of this match (direct link)
created The date of creation of the match (ISO8601)
type The type of match (always "credit")
credit The credit found in the metadata of the image at image_url
image_url The URL of the image where the credit was found in its metadata
page_url The URL of the page where a reference to the image at image_url was found
image The image object (see Image object) matched with the query

Media

The media endpoint allows you to register and manage your media on IMATAG. The management part is quite standard: you PUT your media somewhere, and you can afterward GET it or DELETE it. What sets us apart is that all media you have added IMATAG is registered which means two things:

The flipside is that any media which has been marked but not registered on IMATAG or which has been deleted won't be searched for anywhere and we won't be able to find it's watermark even from a manual query.

Media are organised in a folder tree structure. There are few constraints on the folder structure/naming:

Models

The generic media model is composed of a list of common properties, listed below, and specific sub properties

Media object

This model defines the list of attributes for all objects accessible along the path i.e. folder, image, document, etc.

Argument Description
url The URL of the media
path The path of the media
created The date of creation of the media
type The type of object: folder, image, video, document
children For folder, the list of objects contained in that folder (paginated)
metadata For any type of object, the list of the associated metadata.
image If it exists, details the Image object.
video If it exists, details the Video object.
exclusive For image, indicates whether an image is exclusive or not. If not specified, exclusivity is unknown.

Metadata Object

Example of a metadata object:

{
  "user.campaign": "my new campaign",
  "user.hasBeenValidated": true,
  "user.credited": null, # This field is not saved on media registration, but is deleted on media update
  "customer": "another customer" # This field is not valid
}

metadata is a dictionary containing fields composed of keys and values:

Image Object

Attribute Description
url URL of the actual image file
type type of image, either registered for images registered via the Media API, or web for images found on the Web
width width of the image in pixels
height height of the image in pixels
format format of the image (e.g. jpeg or png)
thumbnail URL of the image thumbnail, null if unavailable
credit credit line of this image, null if empty

Additionally, depending on the type, images have extra fields:

Type registered:

Attribute Description
media_path path of the Media object where the image is registered
media_url URL of the Media object where the image is registered

Type web:

Attribute Description
crawl_date date at which the image was found the first time by our crawlers
page_url URL of the page containing the image
md5 MD5 hash of the image content (optional)
last_modified_date date at which the image file was put on the server from which it was downloaded, if available (optional)

Video Object

Attribute Description
url URL of the actual video file (not always available)
type type of video, set to registered or watermarked respectively for non-watermarked or watermarked videos registered via the Media API
width width of the video in pixels
height height of the video in pixels
thumbnail url of the video thumbnail
duration duration of the video
format format of the video, among the followings: mov, mp4, m4a, 3gp, 3g2, mj2

Additionally, depending on the type, images have extra fields:

Type registered:

Attribute Description
streaming_url URL of a video file optimized for streaming (if available)

Type watermarked:

Attribute Description
secret secret used for the watermark
max_payload max_payload used for the watermark (payload mode only)
payload payload used for the watermark (payload mode only)
original_path path of the Media object where the original video is registered (if available)
original_url URL of the original video file

List a folder

import requests

headers = {
    'Authorization': 'Token <your api token>',
}
response = requests.get('https://imatag.com/api/v3/media/api.demo/images', headers=headers)
curl https://imatag.com/api/v3/media/api.demo/images \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/images",
    "path": "api.demo/images",
    "created": "2018-07-20T15:04:33.221902Z",
    "disk_usage": 242602,
    "type": "folder",
    "thumbnail": null,
    "metadata": {},
    "children_count": 2,
    "subfolders_count": 2,
    "media_count": 0,
    "next": null,
    "previous": null,
    "children": [
        {
            "url": "https://imatag.com/api/v3/media/api.demo/images/paris",
            "path": "api.demo/images/paris",
            "created": "2018-07-20T15:13:06.259863Z",
            "disk_usage": 0,
            "type": "folder",
            "thumbnail": null,
            "metadata": {},
            "children_count": 1,
            "subfolders_count": 0,
            "media_count": 2
        },
        {
            "url": "https://imatag.com/api/v3/media/api.demo/images/new-york",
            "path": "api.demo/images/new-york",
            "created": "2018-07-20T15:16:07.777535Z",
            "disk_usage": 0,
            "type": "folder",
            "thumbnail": null,
            "metadata": {},
            "children_count": 1,
            "subfolders_count": 0,
            "media_count": 4
        }
  ]
}

This endpoint lists the content of a folder at the given path. Note that the children list is paginated so you might have to iterate to get all children. The children attribute is only returned for the current folder and not for any subfolders. If you need the full hierarchy, you will need to recursively GET the url attribute of each subfolder.

HTTP Request

GEThttps://imatag.com/api/v3/media/<homedir>/<path>

URL Parameters

Parameter Required Description
homedir false The user home directory where to list media from (e.g. jdoe).
path false The path of the subfolder(s) to list media from (e.g. images/2018) within a home directory.

Query Parameters

Parameter Default Description
hidden 0 Show hidden folders & media (name starting with '.')

Response description

See Media object

Get a media

import requests

headers = {
    'Authorization': 'Token <your api token>',
}
response = requests.get('https://imatag.com/api/v3/media/api.demo/images/paris/tour-eiffel.jpeg',
                        headers=headers)
curl https://imatag.com/api/v3/media/api.demo/images/paris/tour-eiffel.jpeg \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/images/paris/tour-eiffel.jpeg",
    "path": "api.demo/images/paris/tour-eiffel.jpeg",
    "created": "2018-07-20T15:15:49.548216Z",
    "disk_usage": 97358,
    "type": "image",
    "thumbnail": "https://static1.imatag.com/54578,15ec5ca69f80719a",
    "metadata": {
        "user.subject":"Eiffel Tower",
        "user.campaign":"Paris by night"
    },
    "image": {
        "type": "registered",
        "url": "https://static1.imatag.com/59713,10a05da70fc4",
        "width": 800,
        "height": 500,
        "thumbnail": "https://static1.imatag.com/54578,15ec5ca69f80719a",
        "credit": "© 2012 Cameron Rutt"
    }
}

This endpoint retrieves information about the media at a given path.

HTTP Request

GEThttps://imatag.com/api/v3/media/<homedir>/<path>/<filename>

URL Parameters

Parameter Required Description
homedir true The user home directory where to list media from (e.g. jdoe).
path false The folder(s) path where to store the media within your home directory (e.g. images/2018)
filename true The file name of the file that will be used on our servers (e.g. new-york.jpg)

Response description

See Media object

Register a new media

First example with the lmk file You can download this watermark file to run the example.

import requests

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "application/lmk",
}
lmk = open("./registration.lmk", "rb").read()
response = requests.put("https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
                        data=lmk, headers=headers)

curl -X PUT \
  https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: application/lmk" \
  --data-binary @- < ./registration.lmk

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
    "path": "api.demo/uploads/2018/my-image.jpg",
    "created": "2019-01-02T15:09:17.145580Z",
    "disk_usage": 97358,
    "type": "image",
    "thumbnail": "https://static4.imatag.com/208368,28c25e65d3e1baad",
    "metadata": {},
    "image": {
        "type": "registered",
        "url": "https://static4.imatag.com/20985,28c25e65d3e1baad",
        "width": 800,
        "height": 500,
        "thumbnail": "https://static4.imatag.com/208368,28c25e65d3e1baad"
    }
}

Second example with the JSON file

import requests
import json

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "application/json",
}
data = {
    "url": "https://static3.imatag.com/49785,25dcc2978a4b5bad",
    "metadata": {
        "user.isDemo": "True",
        "user.campaign": "Visit Paris 2020"
    }
}
response = requests.put("https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
                        data=json.dumps(data), headers=headers)

curl -X PUT \
  https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://static3.imatag.com/49785,25dcc2978a4b5bad", "metadata": { "user.isDemo": "True", "user.campaign": "Visit Paris 2020"}}'

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
    "path": "api.demo/uploads/2018/my-image.jpg",
    "created": "2019-01-02T15:09:17.145580Z",
    "disk_usage": 97358,
    "type": "image",
    "thumbnail": "https://static4.imatag.com/208368,28c25e65d3e1baad",
    "metadata": {
        "user.isDemo": "True",
        "user.campaign": "Visit Paris 2020"
    },
    "image": {
        "type": "registered",
        "url": "https://static4.imatag.com/20985,28c25e65d3e1baad",
        "width": 800,
        "height": 500,
        "thumbnail": "https://static4.imatag.com/208368,28c25e65d3e1baad"
    }
}

An additional example data-URI example is given in the Uploads section

This endpoint registers a previously watermarked media using the registration (LMK) file generated by the watermarking software or the API's watermarking endpoint. It also allows to add metadata to the media.

HTTP Request

PUThttps://imatag.com/api/v3/media/<homedir>/<path>/<filename>

URL Parameters

Parameter Required Description
homedir true The home directory where to upload the media. This is generally your own username or another client folder for which you're granted permission (e.g. jdoe)
path false The optional subfolder path, within your home directory, where to store the media (e.g. images/2018)
filename true The file name & extension of the image to register. It will be its name on our servers & in your account.

Request content

The content of the request must be either:

Attribute Required Description
url true URL of the lmk file, for example the on provided by the watermarking endpoint. A data URI can also be used to upload a local LMK file (an example is given in the Uploads section).
metadata false A metadata object

Response description

If the request is successful, the response is the newly created Media object

Modify a media metadata

This example is based on the previous example

import requests
import json

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "application/json",
}
data = '''{
    "metadata": {
        "user.isDemo": null,
        "user.campaign": "Visit Ulaanbaatar 2020"
    }
}'''

response = requests.patch("https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
                           data=json.dumps(data), headers=headers)

curl -X PATCH \
  https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: application/json" \
  -d '{"metadata": { "user.isDemo": null, "user.campaign": "Visit Ulaanbaatar 2020"}}'

The above command returns JSON structured like this:

{}

This endpoint can be used to update metadata after the media creation.

HTTP Request

PATCHhttps://imatag.com/api/v3/media/<homedir>/<path>/<filename>

URL Parameters

Parameter Required Description
homedir true The home directory that contains the media. This is generally your own username or another client folder for which you're granted permission (e.g. jdoe)
path false The optional subfolder path, within your home directory, where the media is stored (e.g. images/2018)
filename true The file name & extension of the image.

Request content

Attribute Required Description
metadata false A metadata object

Response description

If the request is successful, a status code 200 is return, along with an empty JSON.

Register a non-watermarked file for similar tracking only

import requests

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "image/jpeg",
}
image = open("./tour-eiffel.jpeg", "rb").read()
response = requests.put("https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
                        data=image, headers=headers)
curl -X PUT \
  https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: image/jpeg" \
  --data-binary @- < ./tour-eiffel.jpeg
curl -X PUT \
  https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: application/json" \
  --data '{"url" : "https://some.website.com/media/my-image.jpg"}'

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
    "path": "api.demo/uploads/2018/my-image.jpg",
    "created": "2019-01-02T15:09:17.145580Z",
    "disk_usage": 97358,
    "type": "image",
    "thumbnail": "https://static4.imatag.com/208368,28c25e65d3e1baad",
    "metadata": {},
    "image": {
        "type": "registered",
        "url": "https://static4.imatag.com/20985,28c25e65d3e1baad",
        "width": 800,
        "height": 500,
        "thumbnail": "https://static4.imatag.com/208368,28c25e65d3e1baad"
    }
}

This endpoint allows to register a non-watermarked file as a new media. The request is similar to the default media creation, except the content shall be an image or video directly.

This allows limited features with uploaded images or video, compared to watermarked media. Files can only be searched for other file with similar visual content:

For example, similar visual content images can produce matches for the same-looking but different photos, as shown below:

eiffel tower A eiffel tower B

The exception to this is when you register a non-watermarked original video for subsequent watermarked video registration.

Request content

The content of the request must be either:

Supported format

file type content type content
image application/json {"url": "url/of/file.jpg"}
image image/jpg binary file
video application/json {"url": "url/of/file.mp4"}
video video/mp4 binary file
zip application/zip binary file

Response description

If the request is successful, the response is the newly created Media object

Register an exclusive image

import requests

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "image/jpeg",
    "X-Lamark-Exclusive": True,
}
image = open("./tour-eiffel.jpeg", "rb").read()
response = requests.put("https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
                        data=image, headers=headers)
curl -X PUT \
  https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: image/jpeg" \
  -H "X-Lamark-Exclusive: True" \
  --data-binary @- < ./tour-eiffel.jpeg

The above command returns JSON structured like this:

{   
    "type": "image",
    "exclusive": true,
    ...
}

When registering an image, you can flag it as exclusive,

Register a watermarked video

This example is for a watermarked video with payload

import requests
import json

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "application/json",
}
data = {
    "type": "video",
    "url": "https://imatag.com/api/v3/media/api.demo/uploads/original_video.mp4",
    "secret": "my secret video",
    "payload": 5,
    "max_payload": 20,    
}
response = requests.put("https://imatag.com/api/v3/media/api.demo/uploads/watermarked_video.mp4",
                        data=json.dumps(data), headers=headers)

curl -X PUT \
  https://imatag.com/api/v3/media/api.demo/uploads/watermarked_video.mp4 \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: application/json" \
  -d '{"type": "video", "url": "https://imatag.com/api/v3/media/api.demo/uploads/original_video.mp4",\
    "secret": "my secret video", "payload": 5, "max_payload": 20}'

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/uploads/watermarked_video.mp4",
    "path": "api.demo/uploads/watermarked_video.mp4",
    "created": "2019-01-02T15:09:17.145580Z",
    "disk_usage": 31380,
    "type": "video",
    "thumbnail": "http://static4.imatag.com/71,02f024f4def5ac",
    "metadata": {},
    "video": {
        "type": "watermarked",
        "secret": "my secret video",
        "max_payload": 20,
        "payload": 5,
        "url": null,
        "width": 960,
        "height": 540,
        "duration": 18.234883,
        "format": "mov,mp4,m4a,3gp,3g2,mj2",
        "original_path": "api.demo/uploads/original_video.mp4",
        "original_url": "http://static4.imatag.com/270,02f0231374f9b5",
        "thumbnail": "http://static4.imatag.com/71,02f024f4def5ac"
    }
}

There are no "registration file" for video like there are for images. As a consequence registering a watermarked video file requires manually sending several pieces of information including the original (un-watermarked) video file that must be provided as an url.

additional URL Parameters

Parameter Required Description
secret true secret used for the watermark
payload false payload used for the watermark (integer), must be betweend 0 and max_payload
max_payload false max_payload used for the watermark (integer, required if payload is used, must be constant for a given secret and original video).

Register multiple medias from a ZIP

This endpoint allows uploading multiple medias from a ZIP file into a folder at once. The ZIP file can contain mixed medias, such as images, videos or registration files.

import requests

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "application/zip",
}
lmk = open("./my-archive.zip", "rb").read()
response = requests.put("https://imatag.com/api/v3/media/api.demo/uploads/2018",
                        data=lmk, headers=headers)

curl -X PUT \
  https://imatag.com/api/v3/media/api.demo/uploads/2018 \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: application/zip" \
  --data-binary @- < ./my-archive.zip

HTTP Request

PUThttps://imatag.com/api/v3/media/<homedir>/<path>

URL Parameters

Parameter Required Description
homedir true The user home directory where the subfolder will be created (e.g. jdoe).
path true The path of the subfolder to upload the zip to (e.g. images/2017).

Delete an existing media

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.delete("https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
                           headers=headers)
curl -X DELETE \
  https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg \
 -H "Authorization: Token <your api token>"

This endpoint deletes and unregisters an existing media.

HTTP Request

DELETEhttps://imatag.com/api/v3/media/<homedir>/<path>/<filename>

URL Parameters

Parameter Required Description
homedir true The home directory that contains the media. This is generally your own username or another client folder for which you're granted permission (e.g. jdoe)
path false The optional subfolder(s) where the media is stored (e.g. images/2018)
filename true The file name and extention of the media to delete

Create a folder

import requests

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "application/x-directory",
}

response = requests.put(
    "https://imatag.com/api/v3/media/api.demo/uploads/2018",
    headers=headers,
    )

curl -X PUT \
  https://imatag.com/api/v3/media/api.demo/uploads/2018 \
 -H "Authorization: Token <your api token>" \
 -H "Content-Type: application/x-directory"

This endpoint creates an empty folder.

HTTP Request

PUThttps://imatag.com/api/v3/media/<homedir>/<path>

URL Parameters

Parameter Required Description
homedir true The user home directory where the subfolder will be created (e.g. jdoe).
path true The path of the subfolder to create (e.g. images/2017).

Delete an existing folder

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.delete("https://imatag.com/api/v3/media/api.demo/uploads/2018",
                           headers=headers)
curl -X DELETE \
  https://imatag.com/api/v3/media/api.demo/uploads/2018 \
 -H "Authorization: Token <your api token>"

This endpoint deletes a folder and all of its content (subfolders, images, documents, etc.) recursively. All media contained within will be unregistered.

HTTP Request

DELETEhttps://imatag.com/api/v3/media/<homedir>/<path>

URL Parameters

Parameter Required Description
homedir true The user home directory that contains the subfolder to delete (e.g. jdoe).
path true The path of the subfolder to delete (e.g. images/2017).

Move a folder or a media

import requests

headers = {
    "Authorization": "Token <your api token>",
}
data = {
    "url": "<homedir>/<path>",
    "to" : "<homedir>/<other path>",
}
response = requests.post("https://imatag.com/api/v3/media/_move/",
                         json=data, headers=headers)    
curl -L -X POST 'https://imatag.com/api/v3/media/_move/' \
  -H 'Authorization: Token <your api token>' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "url": "{{home}}/{{path}}",
    "to": "{{home}}/{{new_path}}"
  }'

The above command returns JSON structured like this:

{
    "path": "<homedir>/<path>"
}

This endpoint moves a resource to another location

HTTP Request

POSThttps://imatag.com/api/v3/media/_move/

Request content

Attribute Required Description
url true Path of the media to move or rename.
to true New path of the media destination. The path will be created if needed.
If to ends with a /, it will be considered as a folder where to move the media to.
In any other cases, the original url will be moved/renamed to to.

Response description

If the request is successful, the response contains the path of the moved/renamed resource.

Argument Description
path The new path of the media, once moved.

Searches

The searches endpoint allows you to schedule searches on images and, depending on your pricing plan, PDF documents. It also allows you to monitor the status of these searches and once complete, to access their results. Searches scheduled via the API, like automated web and press search will find watermarked and similar matches.

Search object

Searches may be done synchronously or asynchronously depending on the input media type and the expected time required to perform the search.

Synchronous searches are ephemeral and never recorded, but are faster than asynchronous searches.

For synchronous searches, the search object contains the following fields:

Field Description
status The status of the search. Can be: complete or failed
matches When status is complete, the matches list is inlined

For asynchronous searches, the search object contains the following fields:

Field Description
status The status of the search. Can be: complete, failed, pending, in progress, or cancelled,
matches When status is complete, the URL of the list of matches (see Web Match object) found in this search.
progress When status is in progress, an integer representing advancement (in percent).
url The URL of the search
name The name of the search
created The date of creation of the search
type The type of object: image or document
image For image, the static URL of the image.
document For document, the static URL of the document.

List all previous searches

This endpoint lists the asynchronous searches submitted by the user.

import requests

headers = {
    'Authorization': 'Token <your api token>',
}
response = requests.get('https://imatag.com/api/v3/searches/', headers=headers)
curl https://imatag.com/api/v3/searches/ \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "next": null,
    "previous": null,
    "results": [
        {
            "url": "https://imatag.com/api/v3/searches/qYh98JhK3mUa/",
            "type": "image",
            "image": "https://static1.imatag.com/172987,20d82c6c92e0ff2a",
            "name": "https://imatag.com/api/doc/images/tour-eiffel.jpeg",
            "created": "2018-11-08T16:48:11.619025Z",
            "status": "complete",
            "matches": "https://imatag.com/api/v3/searches/qYh98JhK3mUa/matches/"
        },
        {
            "url": "https://imatag.com/api/v3/searches/HTnqefQkb7jq/",
            "type": "image",
            "image": "https://static2.imatag.com/176044,20b70be705dcf657",
            "name": "tour-eiffel.jpg",
            "created": "2018-11-07T13:25:52.277479Z",
            "status": "complete",
            "matches": "https://imatag.com/api/v3/searches/HTnqefQkb7jq/matches/"
        }
    ]
}

HTTP Request

GEThttps://imatag.com/api/v3/searches/

Query Parameters

Parameter Default Description
date null If set, only searches started on that exact date on the date field (or exact date & time) will be shown. This cannot be combined with other date lookups on the same field (gt, lt, etc.)
date_lte null If set, only searches started on that date or earlier on the date field will be shown
date_gte null If set, only searches started on that date or later on the date field will be shown
date_lt null If set, only searches started earlier than that date on the date field will be shown
date_gt null If set, only searches started later than that date on the date field will be shown

Response description

Attribute Description
next url of the next searches in the sequence (null if end is reached)
previous url of the previous searches in the sequence (null at the start)
results list of Search objects (see Search object)

This endpoint retrieves a specific search.

import requests

headers = {
    'Authorization': 'Token <your api token>',
}
response = requests.get('https://imatag.com/api/v3/searches/HTnqefQkb7jq/',
                        headers=headers)
curl hhttps://imatag.com/api/v3/searches/HTnqefQkb7jq/ \
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/searches/HTnqefQkb7jq/",
    "type": "image",
    "image": "https://static2.imatag.com/176044,20b70be705dcf657",
    "name": "tour-eiffel.jpg",
    "created": "2018-11-07T13:25:52.277479Z",
    "status": "complete",
    "matches": "https://imatag.com/api/v3/searches/HTnqefQkb7jq/matches/"
}

HTTP Request

GEThttps://imatag.com/api/v3/searches/<search_id>/

URL Parameters

Parameter Required Description
search_id true The unique id of the search to retrieve.

Response description

See Search object

This endpoint performs a new search from an image, either by uploading it or by providing a publicly accessible url. Depending on your pricing plan, you might be allowed to upload pdf files to search all images in the document. You might also be limited in speed and number of searches.

HTTP Request

POSThttps://imatag.com/api/v3/searches/

Request content

For a search by image, the following parameters are available

Parameter Default Description
file null Query file (image or document) if the request is multipart/form-data, or the URL of the query image or document (Data URIs are supported)
name null If set, name for the search. If unset, the filename of the uploaded "file" will be used.
sync Run the search in synchronous mode if set; default is true for images, false otherwise; synchronous searches are allowed only on images
search_path <homedir> Restrict the search to a specific media path (<homedir>/<path>). Ignored for category web.
mode "near_duplicate" Can be near_duplicate to attempt to find the original image(s) the query is derived from or vice-versa, if the matched original is watermarked, detection will be performed. Alternatively can be set to similar to do a faster search in order to find visually similar images which are not necessarily derived from one another or 'leaks'.
categories [] A list to where to search; for images the default may be changed to one of private (your own images), web (all the images we crawled on the Web)
parameters A dict of parameters (see under)
parameters.transforms ["scale"] geometric transform validation model for images; default is scale (crop/resize no rotation), other allowed values are affine (crop/resize/rotation) or perspective. If mode=leaks, default is ["scale", "perspective"].
parameters.filter_marked false If set, filter the results to only show watermarked results (true) or non-watermarked (false)

For a search by text, the following parameters are available

Parameter Default Description
metadata null Dict that represent metadata to search
type null string to search only specific media type ("image", "video", "folder")
filename null string that represent the exact filename to search (case sensitive)
filename__startswith null string that represent the begining of the filename to search (case sensitive). Minimum length required = 3
sync true Run the search in synchronous mode if set

Response content

The response is one of the following, depending on the sync query parameter:

Multiple search use cases:

Search by binary file

Search with a binary file, by direct upload. (See example)

You can download the registered tour-eiffel.jpeg file from the media example to run the example.

import requests

headers = {
    "Authorization": "Token <your api token>"
}
files = {'file': open('tour-eiffel.jpeg', 'rb')}
response = requests.post("https://imatag.com/api/v3/searches/",
                        files=files, headers=headers)

curl -X POST \
  https://imatag.com/api/v3/searches/ \
  -H "Authorization: Token <your api token>" \
  -F "file=@tour-eiffel.jpeg"

The above commands returns JSON structured like this:

{
    "status": "complete",
    "matches": [
        {
            "id": null,
            "created": "2019-11-18T16:40:11.133727Z",
            "type": "user",
            "watermarked": true,
            "image": {
                "type": "registered",
                "url": "https://static4.imatag.com/54578,15ec5ca69f80719a",
                "width": 1280,
                "height": 1706,
                "thumbnail": "https://static4.imatag.com/211701,81c386bd3eb68eba",
                "credit": null,
                "media_path": "/api.demo/images/paris/tour-eiffel.jpeg",
                "media_url": "https://imatag.com/api/v3/media/api.demo/images/paris/tour-eiffel.jpeg"
            }
        }
    ]
}

Search by file url

Search with a remote image, by providing its public URL. (See example)

alternatively you can perform a request by url

import requests
import json

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "application/json",
}
data = {'file': 'https://imatag.com/api/doc/images/tour-eiffel.jpeg'}
response = requests.post("https://imatag.com/api/v3/searches/",
                        data=json.dumps(data), headers=headers)

curl -X POST \
  https://imatag.com/api/v3/searches/ \
  -H "Authorization: Token <your api token>" \
  -F "file=https://imatag.com/api/doc/images/tour-eiffel.jpeg"

The above commands returns JSON structured like this:

{
    "status": "complete",
    "matches": [
        {
            "id": null,
            "created": "2019-11-18T16:39:02.263262Z",
            "type": "user",
            "watermarked": true,
            "image": {
                "type": "registered",
                "url": "https://static1.imatag.com/54578,15ec5ca69f80719a",
                "width": 1280,
                "height": 1706,
                "thumbnail": "https://static3.imatag.com/211701,81c386bd3eb68eba",
                "credit": null,
                "media_path": "/api.demo/images/paris/tour-eiffel.jpeg",
                "media_url": "https://imatag.com/api/v3/media/api.demo/images/paris/tour-eiffel.jpeg"
            }
        }
    ]
}

Search by text

You can search by text. (See example)

You can perform a text search

import requests
import json

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "application/json",
}
data = {
    "metadata": {
        "user.subject": "Eiffel Tower"   
    },
    "filename" : "tour-eiffel.jpeg",
    "type": "image"
}
response = requests.post("https://imatag.com/api/v3/searches/",
                        data=json.dumps(data), headers=headers)

The above commands returns JSON structured like this:

{
    "status": "complete",
    "matches": [
        {
            "id": null,
            "created": "2020-10-23T13:41:21.743541Z",
            "type": "text",
            "query": {
                "filename": "tour-eiffel.jpeg",
                "type": [
                    "image"
                ],
                "sync": true,
                "metadata": {
                    "user.subject": "Eiffel Tower"
                }
            },
            "media": {
                "metadata": {
                    "user.subject": "Eiffel Tower",
                    "user.campaign": "Paris by night"
                },
                "media_path": "api.demo/images/paris/tour-eiffel.jpeg",
                "media_url": "https://imatag.com/api/v3/media/api.demo/images/paris/tour-eiffel.jpeg"
            }
        }
    ]
}

The search endpoint has a "sync" parameter that can be used to turn on the search asynchronously.

By default, the search is synchronous. An explicit sync disabling to False is required to run in async mode.

(See example)

You can also perform an asynchronous search:

import requests

headers = {
    "Authorization": "Token <your api token>"
}
files = {'file': open('tour-eiffel.jpeg', 'rb'), 'sync': 0}
response = requests.post("https://imatag.com/api/v3/searches/",
                        files=files, headers=headers)

curl -X POST \
  https://imatag.com/api/v3/searches/ \
  -H "Authorization: Token <your api token>" \
  -F "file=@tour-eiffel.jpeg" \
  -F "sync=0"

The above commands returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/searches/HTnqefQkb7jq/",
    "type": "image",
    "image": "https://static2.imatag.com/176044,20b70be705dcf657",
    "name": "tour-eiffel.jpg",
    "created": "2018-11-07T13:25:52.277479Z",
    "status": "pending"
}
import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.delete("https://imatag.com/api/v3/searches/trhPnufS7NxJ/",
                           headers=headers)
curl -X DELETE \
  https://imatag.com/api/v3/media/api.demo/searches/trhPnufS7NxJ/ \
 -H "Authorization: Token <your api token>"

This endpoint deletes an existing search and associated matches.

HTTP Request

DELETEhttps://imatag.com/api/v3/searches/<search_id>/

URL Parameters

Parameter Required Description
search_id true The unique id of the search to retrieve.

Uploads

data-URI example for the media endpoint

import requests
import base64
import json

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "application/json",
}
lmk = open("./registration.lmk", "rb").read()
lmk_base64 = base64.b64encode(lmk)
data = {
    "url": "data:application/lmk;base64,{}".format(lmk_base64),
    "metadata": {
        "user.isDemo": "True",
        "user.campaign": "Visit Paris 2020"
    }
}
response = requests.put("https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
                        data=json.dumps(data), headers=headers)
echo "{ \
   \"url\": \"data:application/lmk;base64,$(base64 -w 0 registration.lmk)\", \
   \"metadata\": { \
        \"user.isDemo\": \"True\", \
        \"user.campaign\": \"Visit Paris 2020\" \
   } \
}" | curl -X PUT \
  https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: application/json" \
  -T -

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
    "path": "api.demo/uploads/2018/my-image.jpg",
    "created": "2019-01-02T15:09:17.145580Z",
    "disk_usage": 97358,
    "type": "image",
    "thumbnail": "https://static4.imatag.com/208368,28c25e65d3e1baad",
    "metadata": {
        "user.isDemo": "True",
        "user.campaign": "Visit Paris 2020"
    },
    "image": {
        "type": "registered",
        "url": "https://static4.imatag.com/20985,28c25e65d3e1baad",
        "width": 800,
        "height": 500,
        "thumbnail": "https://static4.imatag.com/208368,28c25e65d3e1baad"
    }
}

Some of our endpoints support direct binary upload when no additional information is required, however others have optional or mandatory additional fields. In this case the file is provided via URL. If the file is not already accessible on a publicly available URL, we offer two options:

The first one is to use a data URI. This requires you to base64 encode your file but limits the number of consecutive API calls. Data-URIs can be used anywhere that require a URL. An example is provided here for a call to the media endpoint.

Alternatively, the uploads endpoint allows you to store temporarily your images on our servers and get URL which can be used on subsequent API calls. This is particularly useful if you need to use the same file in multiple API calls or when you can't do base-64 encoding on your side.

Upload an image or video

import requests

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "image/jpeg",
}
img = open("./original.jpeg", "rb").read()
response = requests.post(
    "https://imatag.com/api/v3/uploads/",
    data=img, headers=headers)
curl -X POST \
  https://imatag.com/api/v3/uploads/ \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: image/jpeg" \
  --data-binary @- < ./original.jpeg

The above command returns JSON structured like this:

{
    "expiry": "2018-12-28T14:10:24Z",
    "url": "http://static2.imatag.com/208562,27981f5f5ad9e3de"
}

This endpoints stores the image or video on our servers in a temporary collection.

HTTP Request

POSThttps://imatag.com/api/v3/uploads/

Response description

The response indicates the temporary location of the uploaded asset and its expiration.

Attribute Description
url The URL of the uploaded media on our servers
expiry Expiration date of the uploaded media on our servers (approximate)

Watermarking

The watermarking endpoint allows you to apply an invisible watermark on a provided image file.

The watermarked file can then be:

Watermarking a file

Watermarking an image by URL

import requests

headers = {
    "Authorization": "Token <your api token>",
}
data = {
    "url": "https://imatag.com/api/doc/images/tour-eiffel.jpeg",
    "sync": True, # False (default true)
    "timeout" : 120 # number of seconds (default 120)
}
response = requests.post("https://imatag.com/api/v3/watermarking/",
                         json=data, headers=headers)    
curl -X POST \
  https://imatag.com/api/v3/watermarking/ \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: application/json" \
  --data '{"url": "https://imatag.com/api/doc/images/tour-eiffel.jpeg", "sync": true}'

The above command returns JSON structured like this:

{
    "expiry": "2018-12-06T17:26:22Z",
    "original": "http://static1.imatag.com/208141,240d162ab9716c41",
    "watermarked": "http://static2.imatag.com/208141,240d164028af21c7",
    "registration": "http://static4.imatag.com/208145,240d163d6fdc2249"
}

HTTP Request

POSThttps://imatag.com/api/v3/watermarking/

Request content

The content of the request must be either:

Attribute Required Description
url true the URL of the asset "http://..."`
sync false the sync call of the api (true or false, default = true)
timeout false the timeout call of the api

Response description

The response indicates where to download the generated assets and their expiration.

Attribute Description
original The URL of the original full-size image
watermarked The URL of the watermarked full-size image
expiry Expiration date of the watermarked assets on our servers (approximate)
registration The URL of the registration data that should be sent on the media endpoint when watermarking images only

Limited number of watermarking per day

This endpoint has extra rate limits, to allow a maximum number of the watermarking endpoint calls per day i.e. per 24-hours period. The limit & remaining counts are indicated as response headers:

Watermark an image

Watermarking an image by direct upload

import requests

headers = {
    "Authorization": "Token <your api token>",
    "Content-Type": "image/jpeg",
}
img = open("./original.jpeg", "rb").read() # file to watermark
response = requests.post("https://imatag.com/api/v3/watermarking/",
                         data=img, headers=headers)
curl -X POST \
  https://imatag.com/api/v3/watermarking/ \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: image/jpeg" \
  --data-binary @- < ./original.jpeg

The endpoint apply the watermarking on any image, provided in a supported format. See the list of supported formats

The above command returns JSON structured like this:

{
    "expiry": "2018-12-06T17:26:22Z",
    "original": "http://static1.imatag.com/208141,240d162ab9716c41",
    "watermarked": "http://static2.imatag.com/208141,240d164028af21c7",
    "registration": "http://static4.imatag.com/208145,240d163d6fdc2249"
}

Detect a watermarked file

Watermark detection

import requests

headers = {
    "Authorization": "Token <your api token>",
}
data = {
    "query": "http://static2.imatag.com/208141,240d164028af21c7",
    "registration": "http://static4.imatag.com/208145,240d163d6fdc2249"
    # or "registration": "https://imatag.com/api/v3/media/api.demo/images/paris/tour-eiffel.jpeg"
}
response = requests.post(
    "https://imatag.com/api/v3/watermarking/detect/",
    json=data, headers=headers)
curl -X POST \
  https://imatag.com/api/v3/watermarking/detect/ \
  -H "Authorization: Token <your api token>" \
  -H "Content-Type: application/json" \
  --data '{"query": "https://imatag.com/api/doc/images/query.jpeg", "registration": "http://static4.imatag.com/208145,240d163d6fdc2249"}'

The above command returns JSON structured like this:

{
    "marked": true
}

HTTP Request

POSThttps://imatag.com/api/v3/watermarking/detect/

The endpoint allows verifying if an image, aka query, is a watermarked copy of the image from the registration file and optionally the original image (in case of Transactional watermarking).

This is for when you want to do exactly one detection, know exactly which watermark you want to detect and expect a boolean answer. If you want to find ou which watermark, if any, is present in the image (either because you have several watermarked version of the same image or because you are not sure what was the original image), you should use the searches endpoint instead.

Request content

The content of the request must be JSON with following attributes:

Attribute Required Description
query true The URL of the image to check
sync false the sync call of the api (true or false, default = true)
timeout false the timeout call of the api (0 <= integer <= 120, default = 120)
registration false The URL of the registration file (containing the watermark data) for comparison against the query. Data URIs are supported as well as urls of registered images in media.
original false The URL of the original image matching the transactional registration file. Data URIs are supported.
secret false The secret passphrase used during the watermarking process if applicable.
payload_max false Maximum value of the payload integer (0-16777215) if applicable.
transform false geometric transform validation model for images; default is scale (crop/resize no rotation), other allowed values are affine (crop/resize/rotation), perspective or none.

One of registration or secret is required, they are mutually exclusive. If secret is set, original is required as well.

Response description

The response indicates whether the query image is a watermarked copy of the compared registration/original asset(s).

Attribute Description
marked If True, the query is watermarked*.
If False, the query is either too much altered or a different image.

Get the encryption key

Get the encryption key

import requests

headers = {
    "Authorization": "Token <your api token>",
}
response = requests.get(
    "https://imatag.com/api/v3/watermarking/key/",
    headers=headers)
curl https://imatag.com/api/v3/watermarking/key/
 -H "Authorization: Token <your api token>"

The above command returns JSON structured like this:

{
    "key": "-----BEGIN RSA PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DIDAQAB\n-----END RSA PUBLIC KEY-----"
}

HTTP Request

GEThttps://imatag.com/api/v3/watermarking/key/

This endpoint returns the encryption key that can be used by the watermarking software to encrypt the registration file.

Response description

The response contains the key.

Attribute Description
key The RSA public key in PEM format

API Workflows

This section provides information about more complex workflows using our API depending on some use cases.

Register a watermarked image

import requests
TOKEN = "Token <your api token>"

# upload my image to imatag
headers = {"Authorization": TOKEN, "Content-Type": "image/jpeg"}
img = open("./original.jpeg", "rb").read()
response = requests.post(
    "https://imatag.com/api/v3/uploads/",
    data=img, headers=headers)
uploaded_url = response.json()['url']

# watermark the uploaded image
headers = {"Authorization": TOKEN}
data = {"url": uploaded_url}
response = requests.post(
    "https://imatag.com/api/v3/watermarking/",
    json=data, headers=headers)
resp_data = response.json()
watermarked_image = resp_data['watermarked']
registration_file = resp_data['registration']

# register the watermarked image in my media
headers = {"Authorization": TOKEN, "Content-Type": "application/json"}
data = {"url": registration_file}
requests.put(
    "https://imatag.com/api/v3/media/api.demo/uploads/2018/my-image.jpg",
    data=json.dumps(data), headers=headers)

For many companies, tracking illegal use of their images is important. This workflow explains the steps to watermark then register an image into the user account:

Leaks

For IMATAG Leaks users, this section indicates how to use the IMATAG API to be able to manager their campaigns programmatically.

Leaks is composed of two main concepts:

Folders structure

|-- <home directory>
    |-- leaks-campaigns
        |-- <campaign name>
            |-- [.originals]
                |-- <original image name>
                |-- ...                
            |-- <recipient name>
                |-- <watermarked images name>
                |-- ...
            |-- ...
        |-- ...

When using the CLI to create their campaign, the folder & media tree structure must be followed strictly as describe in the right panel →.

With a flat path, it should follow the pattern: <home>/leaks-campaigns/<campaign name>/<recipient name>/<media name>

Create a campaign

Create the campaign

Create the campaign

curl -L -X PUT 'https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}' \
-H 'Content-Type: application/x-directory' \
-H 'Authorization: Token <your api token>'
import requests

url = "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}"

payload={}
headers = {
  'Content-Type': 'application/x-directory',
  'Authorization': 'Token <your api token>'
}

response = requests.request("PUT", url, headers=headers, data=payload)

print(response.text)

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/my-first-campaign",
    "path": "api.demo/leaks-campaigns/my-first-campaign",
    "created": "2022-01-19T15:34:19.279138Z",   
    "type": "folder",
    ...
}

First, You need to manually create the campaign. see how to create a folder

PUT https://imatag.com/api/v3/media/<home>/leaks-campaigns/<campaign>

Then, the campaign folder must contain some metadata to be fully functional by our system:

Set the campaign metadata

curl -L -g -X PATCH 'https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}' \
--data-raw '{
    "metadata": {
        "user.type": "campaign",
        "user.status": "draft"
    }
}'
import requests

url = "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}"

payload = '''{
    "metadata": {
        "user.type": "campaign",
        "user.status": "draft"
    }
}'''
headers = {}

response = requests.request("PATCH", url, headers=headers, data=payload)

print(response.text)

see how to modify the folder metadata

Upload your original files

Upload your original files

curl -L -g -X PUT 'https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}/.originals/{{image.jpeg}}' \
-H 'Content-Type: image/jpeg' \
-H 'Authorization: Token <your api token>' \
--data-binary '@/path/to/your/original/image.jpeg'
import requests

url = "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}/.originals/{{image.jpeg}}"

payload="<file contents here>"
headers = {
  'Content-Type': 'image/jpeg',
  'Authorization': 'Token <your api token>'
}

response = requests.request("PUT", url, headers=headers, data=payload)

print(response.text)

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/my-first-campaign/.originals/my-image.jpeg",
    "path": "api.demo/leaks-campaigns/my-first-campaign/.originals/my-image.jpeg",
    "created": "2022-01-19T16:02:49.648494Z",
    "disk_usage": 82780,
    "type": "image",
    "thumbnail": "http://static2.imatag.com/21,1526522dff",
    "metadata": {},
    "image": {
        "type": "registered",
        "url": "http://static2.imatag.com/12,14d5b20155",
        "width": 1280,
        "height": 853,
        "format": "jpeg",
        "thumbnail": "http://static2.imatag.com/21,1526522dff",
        "credit": null
    }
}

You have two options, for uploading your original assets.

The preferred option is to upload your original assets into the .originals sub-folder of your campaign: <home>/leaks-campaigns/<campaign name>/.originals/ It mainly allows to upload your assets only once, when dealing with a large number of recipients.

Upload your original image by using the additional argument mark: True in the json payload alongside the request content:

You will have to use image.url, from the response, as the original image URL.

The second solution is to use the dedicated endpoint for uploading the image temporary to our servers. Then use that temporary URL to watermark and register copies.

Create the recipients

Create the recipients

curl -L -g -X PUT 'https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}/{{recipient}}' \
-H 'Content-Type: application/x-directory' \
-H 'Authorization: Token <your api token>'
import requests

url = "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}/{{recipient}}"

payload={}
headers = {
  'Content-Type': 'application/x-directory',
  'Authorization': 'Token <your api token>'
}

response = requests.request("PUT", url, headers=headers, data=payload)

print(response.text)

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/my-first-campaign/jondoe",
    "path": "api.demo/leaks-campaigns/my-first-campaign/jondoe",
    "created": "2022-01-19T16:05:27.244851Z",
    "disk_usage": 0,
    "type": "folder",
    "thumbnail": null,
    "metadata": {},
    "children_count": 0,
    "subfolders_count": 0,
    "media_count": 0
}

Create recipients sub-folders under the campaign folder. see how to create a folder

Generate watermarked copies

Generate watermarked copies

curl -L -g -X PUT 'https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}/{{recipient}}/{{watermark.jpeg}}' \
-H 'Authorization: Token <your api token>' \
-H 'Content-Type: application/json' \
--data-raw '{
    "url": "{{original image URL}}",
    "mark": true,
    "metadata": {
        "user.campaign": "{{campaign}}",
        "user.recipient": "{{recipient}}"
    }   
}'
import requests
import json

url = "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}/{{recipient}}/marked.jpeg"

payload = json.dumps({
  "url": "{{original image URL}}",
  "mark": True,
  "metadata": {
    "user.campaign": "{{campaign}}",
    "user.recipient": "{{recipient}}"
  }
})
headers = {
  'Authorization': 'Token <your api token>',
  'Content-Type': 'application/json'
}

response = requests.request("PUT", url, headers=headers, data=payload)

print(response.text)

The above command returns JSON structured like this:

{
    "url": "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/my-first-campaign/jondoe/marked.jpeg",
    "path": "api.demo/leaks-campaigns/my-first-campaign/jondoe/marked.jpeg",
    "created": "2022-01-19T16:22:50.059784Z",
    "disk_usage": 82780,
    "type": "image",
    "thumbnail": "http://static2.imatag.com/16,182d9e9358",
    "metadata": {
        "user.recipient": "jondoe",
        "user.campaign": "my-first-campaign"
    },
    "image": {
        "type": "registered",
        "url": "http://static2.imatag.com/26,17e965ff77",
        "width": 1280,
        "height": 853,
        "format": "jpeg",
        "thumbnail": "http://static2.imatag.com/16,182d9e9358",
        "credit": null
    }
}

You will have to create n watermark copies, one for each recipient, for each image of the campaign.

To do so, we'll consider, you have the original images URLs, not yet watermarked, from your .originals folder (or temporary URL).

You can watermark and register a copy, at once, using the media registration endpoint, providing the extra parameter mark to true.

It's best to also add metadata for registering your new watermark copy, with:

This metadata will be useful to you when trying to find a potential leak. When a leak is detected, the metadata will be provided back to you. With both the campaign & recipient names in the metadata, you will thus be able to easily know/identify the leak.

Set the campaign as complete

Set the campaign as complete

curl -L -g -X PATCH 'https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}' \
-H 'Authorization: Token <your api token>' \
-H 'Content-Type: application/json' \
--data-raw '{
    "metadata": {
        "user.type": "campaign",
        "user.status": "done"
    }
}'
import requests
import json

url = "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}"

payload = json.dumps({
  "metadata": {
    "user.type": "campaign",
    "user.status": "done"
  }
})
headers = {
  'Authorization': 'Token <your api token>',
  'Content-Type': 'application/json'
}

response = requests.request("PATCH", url, headers=headers, data=payload)

print(response.text)

Once all images have been watermarked, for each user, you have to set the campaign as complete (done). This will allow downloading watermarked assets, and forbid for campaign modifications.

This can be done by simply updating the campaign metadata: user.status="done".

Download the watermarked copies

Download the watermarked copies

curl -L -g -X GET 'https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}/_archive/zip/' \
-H 'Authorization: Token <your api token>' \
-o my-archive.zip
import requests

url = "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/{{campaign}}/_archive/zip/"

payload={}
headers = {
  'Authorization': 'Token <your api token>'
}

response = requests.request("GET", url, headers=headers, data=payload)

open('my-campaign.zip', 'wb').write(response.content)

You can either download:

GEThttps://imatag.com/api/v3/media/<home>/leaks-campaigns/<campaign>/_archive/zip/

GEThttps://imatag.com/api/v3/media/<home>/leaks-campaigns/<campaign>/<recipient>/_archive/zip/

Detect a leak

When you have a suspicious image, ie potentially leaked, you can use the searches endpoint to perform a watermark search. The search will be performed across all your watermarked copies from all of your campaigns. When a watermark is found, we will identify the matches and reveal the leak details (campaign & recipient).

First you have to upload temporarily the suspicious image onto our servers, with the upload endpoint.

POST https://imatag.com/api/v3/uploads/

Upload the suspicious image onto our servers

curl -L -X POST 'https://imatag.com/api/v3/uploads/' \
-H 'Content-Type: image/jpeg' \
-H 'Authorization: Token <your api token>' \
--data-binary '@/path/to/your/suspicious/image.jpeg'
import requests

url = "https://imatag.com/api/v3/uploads/"

payload="<file contents here>"
headers = {
  'Content-Type': 'image/jpeg',
  'Authorization': 'Token <your api token>'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

The above command returns JSON structured like this:

{
    "url": "http://static2.imatag.com/4,1a0689a16a",
    "expiry": "2022-01-20T14:37:41Z"
}

This will return you a url of the image, that you can use to make the search query.

POSThttps://imatag.com/api/v3/searches/

Then perform the search, using the URL from the previous call.

curl -L -X POST 'https://imatag.com/api/v3/searches/' \
-H 'Authorization: Token <your api token>' \
-H 'Content-Type: application/json' \
--data-raw '{
    "file": "http://static2.imatag.com/4,1a0689a16a",
    "mode": "leaks"
}'
import requests
import json

url = "https://imatag.com/api/v3/searches/"

payload = json.dumps({
  "file": "http://static2.imatag.com/4,1a0689a16a",
  "mode": "leaks"
})
headers = {
  'Authorization': 'Token <your api token>',
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

The above command returns JSON structured like this:

{
    "status": "complete",
    "matches": [
        {
            "id": null,
            "created": "2022-01-21T12:40:57.699230Z",
            "type": "user",
            "metadata": {
                "user.campaign": "my-first-campaign",
                "user.recipient": "jondoe"
            },
            "watermarked": true,
            "query_format": null,
            "image": {
                "type": "registered",
                "url": "http://10.2.35.3:8080/24,391ba591c5",
                "width": 1280,
                "height": 853,
                "format": "jpeg",
                "thumbnail": "http://10.2.35.3:8080/21,3a0c5bae9a",
                "credit": null,
                "media_path": "api.demo/leaks-campaigns/my-first-campaign/jondoe/marked.jpeg",
                "media_url": "https://imatag.com/api/v3/media/api.demo/leaks-campaigns/my-first-campaign/jondoe/marked.jpeg",
                "metadata": {
                    "user.campaign": "my-first-campaign",
                    "user.recipient": "jondoe"
                }
            }
        }
    ]
}

Request content

Parameter Description
file the URL of the query image (from the upload response)
mode leaks

Response content

As a response, you will get a search object.