Loading...
Guides (For Platforms)
Markdown
Second-Screen QR Codes

The second-screen flow lets a viewer pick up on their phone exactly where they are on the TV.

Your app describes the screen it is showing, Diddo returns a QR code, and scanning it opens the Diddo-hosted second-screen app on the viewer's phone at that same place: a filtered product list, one product, their cart or the checkout.

💡

Unlike QR Code Payments, which hands off a cart that is already built, a second-screen code can hand off any point in the journey, so viewers can browse and build their cart on their phone.


This section covers:

  • How the hand-off works
  • Generating a code for a product list, a product, the cart or the checkout
  • Choosing the image format
  • Size limits and what happens when a payload is too long

🌀 How It Works

  1. Describe the screen

    Your TV app calls the QR endpoint with the view it is showing and the values that view needs, for example the game on screen.

  2. Show the code

    Diddo returns the QR image. Everything the phone needs is encoded in the URL inside it; nothing is stored on our side for the scan.

  3. Customer scan

    The phone opens the second-screen app on your branded Diddo host, already on the right page. A game code opens the game's catalogue, with a switch between the two teams and a link out to the full catalogue.

  4. Shop and pay

    From there the viewer browses, builds a cart and pays on their phone with Apple Pay, Google Pay or a card.

📘 Entity and mode never travel in the request body. Both come from your API key, so a test key always produces a test-mode code.


📱 Sample Second-Screen Flow

A viewer scans a game code, filters to one team, adds a hoodie to their cart and checks out with Google Pay, all in test mode.


Video demo:

second-screen-flow.mp4

🔌 Endpoint

Endpoint:

bash
POST /second-screen/qr

Required Headers:

text
Authorization: Bearer <your_api_key>
Content-Type: application/json

Request Body:

FieldRequiredNotes
view✅list, product, cart or checkout
template_cart_idFor cart and checkoutThe TV's template cart. Optional for list and product. Must be a template cart owned by your entity in your key's mode. checkout also requires it to hold products.
list—Filters for view=list. Optional back-navigation context for view=product.
productFor productproduct_id (required) and variant_id (optional)
screen—A name for the TV screen the code was drawn on, used for scan attribution, e.g. game-shop
qr.size—PNG edge in pixels, 128–2048, default 512. SVG is vector and ignores it.

The list object takes the same names as the Products API: game_id, league, teams, players, category, color, gender, age, brand, tags, sort, min_price, max_price, limit and curated.


🏀 Example: The Game on Screen

The most common code. Name the game and the phone opens that game's catalogue.

json
{
  "view": "list",
  "list": {
    "game_id": "0022500123",
    "league": "nba",
    "teams": ["knicks", "spurs"]
  },
  "screen": "game-shop"
}

cURL Example:

bash
curl --request POST \
  --url 'https://sandbox.api.shopdiddo.com/second-screen/qr.svg' \
  --header 'Authorization: Bearer <your_api_key>' \
  --header 'Content-Type: application/json' \
  --data '{"view":"list","list":{"game_id":"0022500123","league":"nba","teams":["knicks","spurs"]},"screen":"game-shop"}' \
  > qr.svg
💡

Send league and both teams alongside game_id. The teams drive the team switch at the top of the game catalogue.


🛍️ Other Views

A filtered list (no game). Any Products API filter works:

json
{
  "view": "list",
  "list": { "league": "nba", "teams": ["lakers"], "category": ["tops"], "sort": "price_asc" }
}

One product, with the list the viewer came from as the way back:

json
{
  "view": "product",
  "product": { "product_id": "202412345678", "variant_id": "20241234567801" },
  "list": { "league": "nba", "teams": ["lakers"] }
}

The cart or the checkout, once the TV has a template cart:

json
{
  "view": "checkout",
  "template_cart_id": "3b2f89de-c485-4d83-a395-69078186583a"
}

🖼️ Choosing the Format

Suffix the path, or send an Accept header:

You wantRequest
SVG (recommended, scales cleanly)POST /second-screen/qr.svg or Accept: image/svg+xml
PNGPOST /second-screen/qr.png or Accept: image/png
Just the URL, to render your own codePOST /second-screen/qr.json or Accept: application/json

With no Accept header the response is JSON. The .json body carries the encoded url, its size in bytes, the qr_version it needs, and dropped_keys / truncated_keys describing any trimming (see below).

📘

Image responses are sent with Cache-Control: no-store. Request a fresh code each time the TV screen changes.


📏 Size Limits

A code has to stay scannable, so the encoded URL must fit QR version 10 (213 bytes). If your payload is longer, Diddo trims it before refusing it:

  • A product code drops its back-navigation list in one step.
  • A list code drops tags, then curated, then shortens players, teams, category, color, gender and age from the end, one item at a time, until the URL fits.
  • sort, min_price, max_price, limit, mode and screen are never dropped.

Use the .json variant during development to see what, if anything, was trimmed.

A payload still over budget after trimming returns 400 with the untrimmed size, trimmed size and the budget in its details. Error responses follow the same structured format as the Error Handling guide.


🔗 Next: Error Handling →