SDKs and tools

The API is a handful of GET requests, so nothing here is required: a token and an HTTP client are enough. What follows is for the parts that are fiddly to get right the first time. A Postman collection to try the API in, two reference clients thin enough to read in a sitting, and the machine-readable document to generate anything else from.

The Postman collection

Import this URL in Postman and you have every endpoint, with every parameter it accepts and the description of each one, ready to send.

GET
Import from link
https://screenshotbuddy.io/api/v1/postman.json

In Postman, choose Import, then Link, and paste it. The collection is generated when you fetch it, so the base URL inside it is already the one you are reading this on and you never import a stale copy.

Authentication is set once, on the collection rather than on each request. Open the collection's variables and put a token from Settings » API tokens in token; every request that needs one picks it up. The baseUrl variable beside it is what to change if you are pointing the collection at something else.

  • Name
    baseUrl
    Type
    string
    Description

    The base URL every request is built on. It arrives filled in with https://screenshotbuddy.io/api/v1.

  • Name
    token
    Type
    string
    Description

    Your API token, sent as the bearer token of the collection. It arrives empty, because a file people share around is no place for a credential.

Optional parameters are present but switched off, so you can see the whole menu without sending it. Tick the ones you want. The screenshot and PDF requests are separate because they accept different parameters: a parameter sent to the mode it does nothing in is refused rather than ignored, so neither request offers the other's options.

The signed request is the one exception to the collection's authentication: it sends no bearer token, because a signature in the query is what authenticates it. Fill its tokenId and signature variables from your own signing code, which is what the two clients below do for you.

The PHP client

One file, sdks/php/ScreenshotBuddy.php, with no dependencies and nothing to install. Copy it into your project and require it. It needs PHP 8.2 or newer and the curl extension, which is the only thing it uses to make a request.

There is no package to add, and that is on purpose. The file is short enough to read before you trust it, and copying it means an upgrade is something you choose rather than something a dependency resolver does to you at three in the morning.

PHP
capture.php
<?php

require __DIR__ . '/ScreenshotBuddy.php';

$buddy = new ScreenshotBuddy(getenv('SCREENSHOTBUDDY_TOKEN'), 'https://screenshotbuddy.io/api/v1');

try {
    file_put_contents('pricing.png', $buddy->screenshot('https://example.com/pricing', [
        'fullPage' => true,
        'format' => 'jpeg',
        'quality' => 80,
    ]));

    file_put_contents('pricing.pdf', $buddy->pdf('https://example.com/pricing', [
        'paperFormat' => 'a4',
        'landscape' => true,
    ]));

    $usage = $buddy->usage();

    echo $usage['credits']['remaining'], ' credits left', PHP_EOL;
} catch (ScreenshotBuddyError $error) {
    // Branch on the code, never on the message.
    echo $error->errorCode, ': ', $error->getMessage(), PHP_EOL;
    echo 'Quote this at support: ', $error->requestId, PHP_EOL;
}

screenshot() and pdf() return the bytes of the file, because that is what the API answers with. usage() returns the decoded JSON of the usage endpoint. Anything the API refuses is thrown as a ScreenshotBuddyError carrying the code, the message and the request_id out of the error envelope.

The options arrays are the API's query parameters, passed straight through, so the client cannot fall behind the API: a parameter added tomorrow works today. Booleans are converted to the 1 and 0 the API accepts, and an option set to null is left out rather than sent empty.

It also signs. signedUrl() takes the query, a token id and that token's signing secret, and gives you a URL you can put in an <img> tag.

PHP
embed.php
$url = $buddy->signedUrl(
    ['url' => 'https://example.com/pricing', 'width' => 1200, 'height' => 630],
    42,
    getenv('SCREENSHOTBUDDY_SIGNING_SECRET'),
    time() + 3600
);

echo '<img src="' . htmlspecialchars($url) . '" alt="">';

The JavaScript client

The same client as an ES module, sdks/js/screenshotbuddy.mjs. Zero dependencies, built on fetch, with JSDoc types throughout so an editor can tell you what a method returns. Copy it in and import it.

It runs on the server. signedUrl() reaches for node:crypto and takes your signing secret, and a secret that reaches a browser is a secret you have published, as the authentication page warns.

Node.js
capture.mjs
import { writeFile } from 'node:fs/promises';
import { ScreenshotBuddy, ScreenshotBuddyError } from './screenshotbuddy.mjs';

const buddy = new ScreenshotBuddy(process.env.SCREENSHOTBUDDY_TOKEN, 'https://screenshotbuddy.io/api/v1');

try {
  await writeFile('pricing.png', await buddy.screenshot('https://example.com/pricing', {
    fullPage: true,
    format: 'jpeg',
    quality: 80,
  }));

  await writeFile('pricing.pdf', await buddy.pdf('https://example.com/pricing', {
    paperFormat: 'a4',
    landscape: true,
  }));

  const usage = await buddy.usage();

  console.log(`${usage.credits.remaining} credits left`);
} catch (error) {
  if (!(error instanceof ScreenshotBuddyError)) throw error;

  // Branch on the code, never on the message.
  console.error(error.code, error.message, error.requestId);
}

const url = buddy.signedUrl(
  { url: 'https://example.com/pricing', width: 1200, height: 630 },
  42,
  process.env.SCREENSHOTBUDDY_SIGNING_SECRET,
  Math.floor(Date.now() / 1000) + 3600
);

screenshot() and pdf() resolve to a Uint8Array of the file, which is what writeFile and every stream in Node take as is. usage() resolves to the parsed JSON. A refusal rejects with a ScreenshotBuddyError carrying code, message, status and requestId.

Generating a client of your own

Two languages is not many. For anything else, point a generator at the OpenAPI document: it describes every parameter, every status, every header and the full set of error codes, and it is generated from the same definitions the API validates against rather than written alongside them.

GET
/api/v1/openapi.json
curl "https://screenshotbuddy.io/api/v1/openapi.json" --output openapi.json

It needs no token, so a generator in a build step can fetch it without a credential. The one thing to know before you generate: a render answers with the file itself rather than JSON, so tell your generator to treat the 200 of /snap as binary. Everything that is not a 2xx is the same JSON envelope on every endpoint.