Search by Image
curl --request POST \
--url https://api.signa.so/v1/trademarks/search/image \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.signa.so/v1/trademarks/search/image"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.signa.so/v1/trademarks/search/image', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.signa.so/v1/trademarks/search/image",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/trademarks/search/image"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.signa.so/v1/trademarks/search/image")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/trademarks/search/image")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_bodySearch
Search by Image
Find visually similar trademarks by logo/image similarity (beta — not yet generally available)
POST
/
v1
/
trademarks
/
search
/
image
Search by Image
curl --request POST \
--url https://api.signa.so/v1/trademarks/search/image \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.signa.so/v1/trademarks/search/image"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.signa.so/v1/trademarks/search/image', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.signa.so/v1/trademarks/search/image",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/trademarks/search/image"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.signa.so/v1/trademarks/search/image")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/trademarks/search/image")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_bodyBeta — held until GA. Image search is live only for internal and
design-partner keys: it requires the dedicated
image-search:read scope and
is gated off on the free/starter/public plans. This page previews the endpoint
so partners can design against it; shapes may still change before general
availability. It is not yet part of the public API surface.Overview
Upload a logo or image and get back trademarks whose figurative marks look similar — useful for clearance searches, logo lookalikes, and design-mark screening. Works alongside text search (Search Trademarks) and autocomplete (Suggest). The endpoint accepts a multipart image upload, animage_url (https, SSRF-guarded),
or a media_id (reuse an existing mark’s stored logo), and returns a ranked,
mark-level list. Each hit carries a named signals explanation block (visual,
logo_text, exact_dup, vienna_overlap) and a thumbnail URL. Results are a bounded
top-K (limit ≤ 100, no deep pagination); the query image is never stored.
Shape
POST /v1/trademarks/search/image
{
"image_url": "https://example.com/logo.png",
"filters": {
"offices": ["US", "EM"],
"nice_classes": [9, 42]
},
"channels": ["visual", "logo_text", "exact_dup"],
"territory_match": "protection",
"limit": 20
}
territory_match (one of protection or direct, default protection) controls
how any filters.jurisdictions are interpreted: under the default protection a
country code also matches regional rights that protect it (a FR filter includes
EU trade marks), while direct matches only literal territory legs. The response
search_meta echoes the applied mode as search_meta.territory_match.
Request (multipart upload): multipart/form-data with an image file part
(≤ 8 MB, raster only — no SVG) and optional filters / crop / channels /
limit fields (the structured ones JSON-encoded).
Request (existing logo): { "media_id": "med_..." } reuses that media’s
stored vector — no re-embedding.
Response:
{
"object": "list",
"data": [
{
"object": "image_search_hit",
"score": 0.94,
"band": "strong",
"signals": {
"visual": { "score": 0.94, "band": "strong", "embedding_spec": "visual/…" },
"logo_text": null,
"exact_dup": { "checksum_match": false, "phash_distance": null },
"vienna_overlap": null
},
"matched_image": {
"image_id": "img_abc123",
"checksum": "…",
"office": "US",
"jurisdiction": "US",
"thumbnail_url": "/v1/trademarks/image-thumbnails/img_abc123"
},
"thumbnail_url": "/v1/trademarks/image-thumbnails/img_abc123",
"trademark": {
"id": "tm_abc123",
"mark_text": "ACME",
"mark_feature_type": "figurative",
"office_code": "US",
"status": { "primary": "active", "stage": "registered" }
}
}
],
"has_more": false,
"pagination": { "cursor": null, "total_count": 1, "total_count_approximate": false },
"search_meta": {
"search_id": "imgsrch_…",
"query_mode": "image_url",
"channels": ["visual", "logo_text", "exact_dup"],
"territory_match": "protection",
"embedding_spec": "visual/…",
"index_version": 1,
"execution_time_ms": 42
},
"request_id": "req_xyz"
}