Logo just-scan-it
Developer Docs · 7 min read

Just Scan It REST API: The Complete Developer Guide

Table of Contents

Introduction

The Just Scan It REST API gives you full programmatic access to your QR codes, redirect rules, landing pages, and scan analytics. Whether you're building an internal dashboard, automating QR code creation from your CRM, or pulling scan data into your own analytics pipeline — the API has you covered.

Base URL:

https://justscanit.com/api/v1

All endpoints return JSON and require authentication.


Authentication

The API uses OAuth 2.0 Personal Access Tokens via Laravel Passport.

Getting your token

  1. Log in to your Just Scan It dashboard
  2. Navigate to API Keys in the sidebar
  3. Click Create new token
  4. Select the scopes you need (see below)
  5. Copy the token — it will only be shown once

Using your token

Include the token in every request as a Bearer token:

Authorization: Bearer YOUR_TOKEN_HERE

Available scopes

Scope Description
read View QR codes, landing pages, and user info
write Create and update QR codes, redirect rules, and landing pages
delete Delete QR codes, redirect rules, and landing pages
scans:read View scan analytics and summaries

You only need to request the scopes your integration actually uses. A read-only dashboard? Just request read and scans:read.

Requirements

  • You must have an active subscription or credits on your account to access the API.
  • API requests are scoped to your current team context automatically.

Pagination

All list endpoints return paginated results. The default page size is 15 items per page, with a maximum of 100.

GET /api/v1/qr-codes?per_page=25&page=2

Paginated responses include a meta object with current_page, last_page, per_page, and total.


QR Codes

QR codes are the heart of Just Scan It. Each QR code has a unique slug and a public redirect URL.

List QR codes

GET /api/v1/qr-codes

Scope: read

Query parameters:

Parameter Type Description
filter[type] string Filter by static or dynamic
filter[is_active] boolean Filter by active status
filter[content_type] string Filter by url, file, landing_page, or landing_page_block
sort string Sort field. Prefix with - for descending. Options: created_at, name, updated_at
per_page integer Results per page (1–100, default 15)

Example request:

curl -X GET "https://justscanit.com/api/v1/qr-codes?filter[type]=dynamic&sort=-created_at" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Accept: application/json"

Example response:

{
  "data": [
    {
      "id": 1,
      "name": "Spring Campaign",
      "slug": "spring-2026",
      "type": "dynamic",
      "target_url": "https://example.com/spring",
      "fallback_url": null,
      "is_active": true,
      "content_type": "url",
      "expires_at": null,
      "licensed_until": "2027-04-01T00:00:00Z",
      "auto_renew": true,
      "public_url": "https://justscanit.com/r/spring-2026",
      "options": {},
      "created_at": "2026-03-15T10:30:00Z",
      "updated_at": "2026-03-15T10:30:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 15,
    "total": 1
  }
}

Get a single QR code

GET /api/v1/qr-codes/{id}

Scope: read

Returns the full QR code object including its redirect rules and associated landing page (if any).

Create a QR code

POST /api/v1/qr-codes

Scope: write

Body parameters:

Parameter Type Required Description
name string Yes A descriptive name for the QR code
type string Yes static or dynamic
target_url string Conditional Required when content_type is url
content_type string No url (default), file, landing_page, or landing_page_block
fallback_url string No Fallback URL when redirect rules don't match
is_active boolean No Whether the QR code is active (default: true)
auto_renew boolean No Automatically renew with credits when license expires
options object No Visual customization options (colors, logo, etc.)

Example request:

curl -X POST "https://justscanit.com/api/v1/qr-codes" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Summer Sale QR",
    "type": "dynamic",
    "target_url": "https://shop.example.com/summer",
    "fallback_url": "https://shop.example.com",
    "auto_renew": true
  }'

Update a QR code

PUT /api/v1/qr-codes/{id}

Scope: write

Accepts the same body parameters as creation. Only include the fields you want to change.

Delete a QR code

DELETE /api/v1/qr-codes/{id}

Scope: delete

Returns 204 No Content on success.


Redirect Rules

Redirect rules let you route scans to different URLs based on device type, country, time of day, or day of the week. Rules are evaluated by priority — the first matching rule wins.

List redirect rules

GET /api/v1/qr-codes/{qrCodeId}/rules

Scope: read

Create a redirect rule

POST /api/v1/qr-codes/{qrCodeId}/rules

Scope: write

Body parameters:

Parameter Type Required Description
url string Yes The destination URL for this rule
device string No Target device: ios, android, windows, mac, linux, etc.
country_code string No ISO 3166-1 alpha-2 country code (e.g. NL, US, DE)
start_at datetime No Rule becomes active at this time
end_at datetime No Rule expires at this time
days_of_week array No Array of days: ["monday", "tuesday", ...]
priority integer No Lower number = higher priority (default: 0)
weight integer No For weighted random distribution among same-priority rules
is_active boolean No Whether the rule is active (default: true)

Example — send iOS users to the App Store:

curl -X POST "https://justscanit.com/api/v1/qr-codes/1/rules" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://apps.apple.com/app/your-app/id123456",
    "device": "ios",
    "priority": 1
  }'

Example — weekday-only promotion for German users:

curl -X POST "https://justscanit.com/api/v1/qr-codes/1/rules" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://shop.example.com/de/weekday-deal",
    "country_code": "DE",
    "days_of_week": ["monday", "tuesday", "wednesday", "thursday", "friday"],
    "start_at": "2026-04-01T08:00:00Z",
    "end_at": "2026-06-30T22:00:00Z",
    "priority": 2
  }'

Update a redirect rule

PUT /api/v1/qr-codes/{qrCodeId}/rules/{ruleId}

Scope: write

Delete a redirect rule

DELETE /api/v1/qr-codes/{qrCodeId}/rules/{ruleId}

Scope: delete


Scan Analytics

Pull detailed scan data or quick summaries for any QR code.

List scans

GET /api/v1/qr-codes/{qrCodeId}/scans

Scope: scans:read

Returns a paginated list of individual scans with device, country, referrer, UTM parameters, and timestamp data.

Example response:

{
  "data": [
    {
      "id": 42,
      "device": "ios",
      "country_code": "NL",
      "referer": "https://instagram.com",
      "utm_source": "instagram",
      "utm_medium": "social",
      "utm_campaign": "spring_launch",
      "resolved_url": "https://shop.example.com/spring",
      "created_at": "2026-03-20T14:22:00Z"
    }
  ]
}

Scan summary

GET /api/v1/qr-codes/{qrCodeId}/scans/summary

Scope: scans:read

Returns aggregated statistics: total scans, scans this month, top devices, top countries, and more. Perfect for dashboards and reports.


Landing Pages

Create and manage link-in-bio style landing pages that can be linked to QR codes.

List landing pages

GET /api/v1/landing-pages

Scope: read

Get a single landing page

GET /api/v1/landing-pages/{id}

Scope: read

Create a landing page

POST /api/v1/landing-pages

Scope: write

Body parameters:

Parameter Type Required Description
title string Yes Page title
description string No Page description for SEO
preset string No Theme preset: minimal, dark, colorful, corporate, nature, neon, pastel

Update a landing page

PUT /api/v1/landing-pages/{id}

Scope: write

Delete a landing page

DELETE /api/v1/landing-pages/{id}

Scope: delete


User Info

GET /api/v1/user

Scope: read

Returns the authenticated user's profile, including current plan, credits balance, and team context.


Error Handling

The API uses standard HTTP status codes:

Code Meaning
200 Success
201 Created
204 Deleted (no content)
401 Unauthorized — invalid or missing token
402 Payment required — no active subscription or credits
403 Forbidden — insufficient scope or permissions
404 Resource not found
422 Validation error — check the errors object in the response
429 Rate limited — too many requests

Validation error example:

{
  "message": "The name field is required.",
  "errors": {
    "name": ["The name field is required."]
  }
}

Rate Limiting

API requests are rate-limited to protect the platform. If you hit the limit, you'll receive a 429 response with a Retry-After header indicating how many seconds to wait.


Tips & Best Practices

  • Use the narrowest scope possible. A reporting integration only needs read and scans:read.
  • Store tokens securely. Treat API tokens like passwords — never commit them to source control.
  • Use pagination. Don't try to fetch all records at once. Use per_page and page parameters.
  • Check licensed_until before assuming a dynamic QR code is active. Expired licenses stop redirecting.
  • Use auto_renew: true with credits to prevent QR codes from going offline unexpectedly.
  • Set a fallback_url on dynamic QR codes so scans still land somewhere if no redirect rules match.