# Example usage
if __name__ == "__main__":
    # options
    params = {
        "access_key": "your_access_key",
        "url": "https://example.com",
        "format": "jpeg",
        "viewport_width": 1920,
        "viewport_height": 1080
    }
    
    secret_key = "your_secret_key"
    
    # generate signature
    signature = generate_signature(params, secret_key)
    
    print("Parameters:", params)
    print("Query string:", urllib.parse.urlencode(params, doseq=True))
    print("Signature:", signature)
    
    query_string = urllib.parse.urlencode(params, doseq=True)
    final_url = f"https://api.screenshotone.com/take?{query_string}&signature={signature}"
    print("\nAPI URL:", final_url)
```

### JavaScript

Or in JavaScript:

```javascript
// npm install @peculiar/webcrypto
import { Crypto } from "@peculiar/webcrypto";

const encoder = new TextEncoder();

export async function signQueryString(queryString: string, secretKey: string) {
    const webCrypto =
        typeof globalThis.crypto !== "undefined"
            ? globalThis.crypto
            : new Crypto();

    let algorithm = { name: "HMAC", hash: "SHA-256" };
    let key = await webCrypto.subtle.importKey(
        "raw",
        encoder.encode(secretKey),
        algorithm,
        false,
        ["sign", "verify"]
    );
    const digest = await webCrypto.subtle.sign(
        algorithm.name,
        key,
        encoder.encode(queryString)
    );

    const signature = Array.from(new Uint8Array(digest))
        .map((b) => b.toString(16).padStart(2, "0"))
        .join("");

    return signature;
}

// example usage
const query = new URLSearchParams({
    access_key: "your_access_key",
    url: "https://example.com"
});
let queryString = query.toString();

const signature = await signQueryString(queryString, "your_secret_key");
queryString += "&signature=" + signature;

console.log(queryString);
```

## Require signing

After you start signing requests and make sure that the API accepts your requests, you can require signing every request.
Go to [the access configuration page](https://dash.screenshotone.com/access) and enforce signing every request.
The change will be applied immediately, but cached screenshots might not be impacted.
That's it. After this step, unsigned requests with your API access key are not accepted.

## Animated screenshots 

[Animated screenshots](/docs/animated-screenshots/) also support signed links. There is no difference in the underlying mechanism besides that the URL prefix should be `/animate`.