QR Code Generator API

Generate branded QR codes (PNG/JPG/SVG) with shapes, per-eye colors, logos and promo frames.

What you can do
Custom shapes & colors

Dot/square modules + circular/square eyes, with per-eye colors.

Center logos

Drop a logo in the middle (upload or preset like “scan-me”).

Promo frames

Bottom banner, top header, speech bubble, ribbon tag, badge.

Save & CDN-ready

Store to disk and get a public URL back instantly.

Try Live
99.9 % Uptime
Response
20 req/s
0 Credits / request

Generate QR Code

POST https://api.yeb.to/v1/qr-code/generate
Parameter Type Req Description
api_keystringyesYour API key.
qr_code_textstringyesText/URL encoded into the QR.
image_formatstringoptSVG (default) | PNG | JPG
image_widthintoptTarget width in px (default 500 for raster).
foreground_colorhexoptDefault #000000.
background_colorhexoptDefault #FFFFFF.
body_stylestringoptsquare (default) | dot (PNG/JPG only)
eye_stylestringoptsquare (default) | circle (PNG/JPG only)
eye_outer_color / eye_inner_colorhexoptGlobal fallback per-eye color.
eye1_outer_color / eye1_inner_colorhexoptTop-left eye colors.
eye2_outer_color / eye2_inner_colorhexoptTop-right eye colors.
eye3_outer_color / eye3_inner_colorhexoptBottom-left eye colors.
qr_code_logostringoptno-logo (default) | scan-me | scan-me-square | upload
logo_path / logo_data_base64stringoptUsed when qr_code_logo=upload.
frame_namestringoptno-frame (default) | bottom-banner | top-header | speech-bubble | ribbon-tag | badge
frame_colorhexoptCTA strip/badge color. Default #000000.
frame_text / frame_text_colorstring/hexoptText like “Scan me”, “Rate us”, etc.; default text color #FFFFFF.
frame_icon_namestringoptIcon filename (resolved in config('qr.icons_path')).
download0|1optClient-handled.
save0|1optSave to disk and return file_url/file_path.
storage_disk / storage_folder / filenamestringoptWhen save=1.
include_bytes0|1optInclude base64 data URI in response (default 1; if save=1, default 0).
curl -X POST https://api.yeb.to/v1/qr-code/generate \
  -H "Content-Type: application/json" \
  -d '{"api_key":"YOUR_KEY","qr_code_text":"https://yeb.to","image_format":"PNG","image_width":600,"foreground_color":"#111111","background_color":"#FFFFFF","body_style":"dot","eye_style":"circle","eye1_outer_color":"#111111","eye1_inner_color":"#FF4D4D","eye2_outer_color":"#111111","eye2_inner_color":"#FFB84D","eye3_outer_color":"#111111","eye3_inner_color":"#4DD2FF","qr_code_logo":"scan-me","frame_name":"bottom-banner","frame_color":"#111111","frame_text":"Scan me","frame_text_color":"#FFFFFF","frame_icon_name":"qr","save":1,"storage_disk":"public","storage_folder":"qr_codes","include_bytes":0}'
$payload = {
    "api_key": "YOUR_KEY",
    "qr_code_text": "https://yeb.to",
    "image_format": "PNG",
    "image_width": 600,
    "foreground_color": "#111111",
    "background_color": "#FFFFFF",
    "body_style": "dot",
    "eye_style": "circle",
    "eye1_outer_color": "#111111",
    "eye1_inner_color": "#FF4D4D",
    "eye2_outer_color": "#111111",
    "eye2_inner_color": "#FFB84D",
    "eye3_outer_color": "#111111",
    "eye3_inner_color": "#4DD2FF",
    "qr_code_logo": "scan-me",
    "frame_name": "bottom-banner",
    "frame_color": "#111111",
    "frame_text": "Scan me",
    "frame_text_color": "#FFFFFF",
    "frame_icon_name": "qr",
    "save": 1,
    "storage_disk": "public",
    "storage_folder": "qr_codes",
    "include_bytes": 0
};
$r = Http::post('https://api.yeb.to/v1/qr-code/generate', $payload);
print_r($r->json());
fetch('https://api.yeb.to/v1/qr-code/generate', {
  method: 'POST',
  headers: {'Content-Type':'application/json'},
  body: JSON.stringify({"api_key":"YOUR_KEY","qr_code_text":"https://yeb.to","image_format":"PNG","image_width":600,"foreground_color":"#111111","background_color":"#FFFFFF","body_style":"dot","eye_style":"circle","eye1_outer_color":"#111111","eye1_inner_color":"#FF4D4D","eye2_outer_color":"#111111","eye2_inner_color":"#FFB84D","eye3_outer_color":"#111111","eye3_inner_color":"#4DD2FF","qr_code_logo":"scan-me","frame_name":"bottom-banner","frame_color":"#111111","frame_text":"Scan me","frame_text_color":"#FFFFFF","frame_icon_name":"qr","save":1,"storage_disk":"public","storage_folder":"qr_codes","include_bytes":0})
}).then(r => r.json()).then(console.log);
import requests, json
payload = {
    "api_key": "YOUR_KEY",
    "qr_code_text": "https://yeb.to",
    "image_format": "PNG",
    "image_width": 600,
    "foreground_color": "#111111",
    "background_color": "#FFFFFF",
    "body_style": "dot",
    "eye_style": "circle",
    "eye1_outer_color": "#111111",
    "eye1_inner_color": "#FF4D4D",
    "eye2_outer_color": "#111111",
    "eye2_inner_color": "#FFB84D",
    "eye3_outer_color": "#111111",
    "eye3_inner_color": "#4DD2FF",
    "qr_code_logo": "scan-me",
    "frame_name": "bottom-banner",
    "frame_color": "#111111",
    "frame_text": "Scan me",
    "frame_text_color": "#FFFFFF",
    "frame_icon_name": "qr",
    "save": 1,
    "storage_disk": "public",
    "storage_folder": "qr_codes",
    "include_bytes": 0
}
        r = requests.post('https://api.yeb.to/v1/qr-code/generate', headers={'Content-Type':'application/json'}, data=json.dumps(payload))
print(r.json())

Response Example

{
  "mime": "image/png",
  "ext": "png",
  "width": 720,
  "height": 880,
  "saved": true,
  "file_url": "https://cdn.your-site/qr_codes/2025/08/21/qr-...png",
  "file_path": "qr_codes/2025/08/21/qr-...png",
  "meta": {
    "format": "PNG",
    "frame_applied": true,
    "logo": "scan-me",
    "colors": { "foreground":"#111111","background":"#FFFFFF","eye1_outer":"#111111","eye1_inner":"#FF4D4D","eye2_outer":"#111111","eye2_inner":"#FFB84D","eye3_outer":"#111111","eye3_inner":"#4DD2FF" },
    "shape": { "body":"dot", "eye":"circle" },
    "frame": { "name":"bottom-banner","color":"#111111","text":"Scan me","textColor":"#FFFFFF","icon":"qr" },
    "download": false,
    "saved": true
  },
  "data_base64": null
}
{
  "error": "qr_code_text is required",
  "code": 422
}

Response Codes

CodeDescription
200 SuccessRequest processed OK.
400 Bad RequestInput validation failed.
401 UnauthorizedMissing / wrong API key.
403 ForbiddenKey inactive or not allowed.
429 Rate LimitToo many requests.
500 Server ErrorUnexpected failure.

Frequently Asked Questions

SVG is ideal for print and high-DPI screens (vector). PNG/JPG are raster; use them when you need custom shapes, per-eye colors, or frames.

Use dark modules on a light background, keep good contrast, avoid busy images behind the code, and don’t exceed ~25–30% logo size.

We use High (H), roughly up to ~30% damage tolerance in ideal conditions.

Yes, 4 modules of margin around the QR are enforced.

Frames are applied to raster outputs (PNG/JPG). SVG uses the base QR only.

Hex #RRGGBB. Invalid values fall back to #000000.

On the configured Laravel disk (default public) under {folder}/YYYY/MM/DD. The API returns file_url and file_path.

When include_bytes=1, we return a data URI string (e.g., data:image/png;base64,...) for direct embedding.

Yes. Every request, even those resulting in errors, consumes credits. This is because your credits are strictly tied to the number of requests, regardless of success or failure. However, if the error is clearly due to a platform problem on our end, we’ll recover those credits for you.

Contact us at [email protected]. We take feedback seriously—if your bug report or feature request is meaningful, we can fix or improve the API quickly and grant you 50 free credits as a thank you.

It depends on the API and sometimes even on the endpoint. Some endpoints use data from external sources, which may have stricter limits. We also enforce limits to prevent abuse and keep our platform stable. Check the docs for the specific rate limit for each endpoint.

We operate on a credit system. Buy once—credits never expire. They’re non-refundable units for making API calls (requests). Simple, fair, and you top up only when you need more.

Every HTTP call is one request. Each request consumes a number of credits depending on the endpoint. In most cases, you can make thousands of requests with just one credit—but always check each endpoint for its cost.

Yes. Your credits never expire until you use them, but they are non-refundable.

Credits are non-refundable. Only buy what you need—you can always top-up later. If we screw up and it costs you, we’ll fix it.

Prices are set in credits, not dollars. Each endpoint lists its own cost—see the “Credits / request” badge above. You’ll always know exactly what you’re spending.
← Back to APIs