Skip to main content

Quickstart Tutorial

Protect your first image and get back its SignatureID. The tutorial takes about 10 minutes.

Steps

  1. Get an access token.
  2. Submit an image.
  3. Poll the job until it completes.
  4. Download the protected image.

Before you start

  • A Client ID and Client Secret from SASHA (Prerequisites)
  • A JPEG or PNG image, as a public URL or a local file
  • A terminal
tip

This tutorial polls for job status. In production, set up callbacks instead: SASHA posts the finished job to your endpoint, so your service makes no status requests.

gRPC prerequisites

For gRPC you also need a gRPC client such as nice-grpc, and client code generated from the SASHA .proto files.

Step 1: Get an access token

Exchange your client credentials for an access token.

Replace YOUR_CLIENT_ID and YOUR_CLIENT_SECRET with your own credentials:

curl https://partner.api.sasha.eu/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-d "grant_type=client_credentials"

Response:

{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600
}
info

Keep the access_token value for the next steps. The token expires after expires_in seconds.

Step 2: Submit the image

Submit the image URL to the Partner API. SASHA fetches the image and returns a job.

curl https://partner.api.sasha.eu/signature/embed \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"media_url": "https://developer.sasha.eu/img/sasha-logo-wall.jpeg",
"media_mime_type": "image/jpeg"
}'

Response:

{
"job": {
"job_id": "44cab986-0385-470a-8e5c-c657b0543d19",
"type": "embed-signature",
"status": "pending",
"created_at": "2025-10-07T12:00:00Z",
"updated_at": "2025-10-07T12:00:00Z"
}
}
info

Keep the job_id value. Step 3 uses it to read the job status.

Alternative: upload the file directly

To send a local file, use multipart/form-data (REST) or the EmbedSignatureFromData streaming method (gRPC). See Embed Signature.

Step 3: Poll the job

Read the job every 2 seconds until status is completed. Most jobs complete within 1 second.

curl https://partner.api.sasha.eu/jobs/44cab986-0385-470a-8e5c-c657b0543d19 \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response (while processing):

{
"job_id": "44cab986-0385-470a-8e5c-c657b0543d19",
"type": "embed-signature",
"status": "in_progress",
"created_at": "2025-10-07T12:00:00Z",
"updated_at": "2025-10-07T12:00:01Z"
}

Response (when complete):

{
"job_id": "44cab986-0385-470a-8e5c-c657b0543d19",
"type": "embed-signature",
"status": "completed",
"output_url": "https://storage.sasha.eu/protected/abc123.jpg",
"output_url_expires_at": "2025-10-07T13:00:00Z",
"signature_id": "12345678901234567890",
"creator_id": 123,
"created_at": "2025-10-07T12:00:00Z",
"updated_at": "2025-10-07T12:00:05Z"
}

Step 4: Download the protected image

Download the image from output_url.

curl -o protected-image.jpg "https://storage.sasha.eu/protected/abc123.jpg"
The URL expires

output_url stops working at the time in output_url_expires_at. Download the image before then.

Result

You now have:

  • job_id — the identifier of the embed job
  • signature_id — the public handle for this Signature
  • creator_id — the CreatorID of the partner that protected the image
  • A protected image that looks identical to the original and carries the Signature

Look the Signature up

Confirm the Signature is in the image by looking it up.

curl https://partner.api.sasha.eu/signature/lookup \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"media_url": "[USE_OUTPUT_URL_FROM_STEP_3]",
"media_mime_type": "image/jpeg"
}'

Replace [USE_OUTPUT_URL_FROM_STEP_3] with the output_url from Step 3.

The signature_id the lookup returns matches the one from your embed job.

Common issues

IssueFix
401 UnauthorizedThe token expired, or the credentials are wrong. Request a new token.
400 Bad Request, media_url is requiredSend media_url and media_mime_type in a JSON body.
Job status is failed, error unsupported_formatConvert the image to JPEG or PNG.
404 Not Found on output_urlThe URL expired. Read output_url_expires_at, then run the embed job again.

Next steps

Before you go to production
  1. Replace polling with callbacks.
  2. Cache the access token. Renew it 60 seconds before expires_in.
  3. Retry a failed job only on failed_to_fetch_from_url and internal.