MakeFav API dokumentācija
Ģenerējiet pilnus favicon komplektus no sava koda, būvēšanas skriptiem un CI konveijeriem. Ar vienu pieprasījumu jebkurš attēls kļūst par favicon.ico, Apple touch ikonām, Android un PWA ikonām, tīmekļa manifestu un gatavu HTML kodu.
Šajā lapā
Ātrā sākšana
MakeFav API ir vienkāršs HTTPS + JSON REST API. Visi galapunkti atrodas zem viena bāzes URL:
https://makefav.com/api/v1 - Izveidojiet bezmaksas kontu
Reģistrējieties, apstipriniet e-pasta adresi un saglabājiet aktīvu MakeFav jaunumu abonementu – tas ir vienīgais bezmaksas plāna nosacījums. - Izveidojiet API atslēgu
Atveriet sava konta lapu API atslēgas un izveidojiet personīgo atslēgu. Tā sākas ar mf_ un tiek parādīta tikai vienu reizi, tāpēc glabājiet to drošībā. Pārvaldīt API atslēgas - Nosūtiet savu pirmo pieprasījumu
Augšupielādējiet attēlu ģenerēšanas galapunktā un saglabājiet atgriezto ZIP failu:
curl --fail-with-body -sS https://makefav.com/api/v1/generate \
-H "Authorization: Bearer $MAKEFAV_API_KEY" \
-F "[email protected]" \
-F "app_name=My App" \
-F "theme_color=#2f9e68" \
-F "radius=20" \
-o favicons.zip Unzip favicons.zip, upload the files to your website and paste the HTML code from the end of readme-makefav.txt into the <head> of every page.
Autentifikācija
Katram pieprasījumam aizsargātā galapunktā jāiekļauj personīgā API atslēga. Atslēgas varat izveidot, nosaukt un atsaukt jebkurā laikā sava konta lapā: API atslēgas
Send the key as a bearer token in the Authorization header, or – if your HTTP client makes that awkward – in the X-API-Key header. Both are equivalent.
Authorization: Bearer mf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# or, alternatively
X-API-Key: mf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Missing or invalid keys return 401 Unauthorized. The GET /sizes and GET /openapi.json endpoints do not require a key.
Pieprasījumu ierobežojumi
Pēc noklusējuma katra API atslēga drīkst veikt 100 pieprasījumus stundā. Katra autentificētā atbilde parāda, cik daudz jums vēl ir atlicis:
| Galvene | Apraksts |
|---|---|
X-RateLimit-Limit | Maksimālais pieprasījumu skaits, kas atļauts pašreizējā periodā. |
X-RateLimit-Remaining | Atlikušie pieprasījumi pašreizējā periodā. |
X-RateLimit-Reset | Unix laikspiedols (sekundēs, UTC), kad periods tiek atiestatīts. |
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1767225600 When the limit is exceeded the API responds with HTTP 429 and the error code rate_limited. Wait until the time in X-RateLimit-Reset before retrying – do not retry in a tight loop.
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1767225600
{"error": {"code": "rate_limited", "message": "Rate limit exceeded. Try again after the reset time."}} You can check your current quota at any time with GET /me.
Galapunkti
| Galapunkts | Autentifikācija | Apraksts |
|---|---|---|
POST /generate | API atslēga | Izveidot pilnu favicon komplektu. |
GET /me | API atslēga | Jūsu konts un pašreizējais pieprasījumu ierobežojuma statuss. |
GET /sizes | Nav | Visu ikonu failu un izmēru saraksts, ko ģenerators izveido. |
GET /openapi.json | Nav | Mašīnlasāma OpenAPI 3.1 specifikācija. |
Ģenerēt favicon paketi
/generateIzveido pilnu favicon paketi no viena avota attēla. Nosūtiet attēlu vienā no trim veidiem:
| Satura veids | Attēla lauks | Apraksts |
|---|---|---|
multipart/form-data | image | Faila augšupielāde. Ieteicams – visefektīvākā iespēja. |
application/json | image_base64 | Base64-encoded image, either raw base64 or a data URL such as data:image/png;base64,iVBOR…. |
application/json | image_url | Attēla publiskais http vai https URL. Serveris to lejupielādē (maks. 10 MB). |
Atbalstītie ievades formāti: PNG, JPG, WebP, AVIF, GIF, BMP, SVG un ICO. Maksimālais faila izmērs: 10 MB.
Parametri
Visi parametri ir neobligāti. Sūtiet tos kā formas laukus (multipart) vai JSON īpašības. Nederīgas vērtības tiek aizstātas ar noklusējuma vērtību.
| Vārds | Tips / diapazons | Noklusējums | Apraksts |
|---|---|---|---|
app_name | virkne, maks. 60 rakstzīmes | My Website | Jūsu vietnes vai lietotnes nosaukums, tiek izmantots manifest.json un piemēra lapā. |
short_name | virkne, maks. 24 rakstzīmes | pirmās 12 app_name rakstzīmes | Īsais nosaukums, kas tiek rādīts zem ikonas Android sākuma ekrānos. |
theme_color | #rrggbb | #ffffff | Pārlūka saskarnes krāsa (theme-color meta tags un manifests). |
tile_color | #rrggbb | tāda pati kā theme_color | Windows sākuma flīžu fona krāsa. |
background | transparent | #rrggbb | transparent | Pārlūka, Android un Windows ikonu fons. |
apple_background | #rrggbb | #ffffff | Apple touch ikonu un maskable ikonas fons (iOS neatbalsta caurspīdīgumu). Tiek ignorēts, ja fons ir krāsa – tad tiek izmantota šī krāsa. |
padding | vesels skaitlis, 0–40 (%) | 0 | Tukša vieta ap attēlu procentos no ikonas izmēra. |
radius | vesels skaitlis, 0–50 (%) | 0 | Noapaļoti stūri. Ar 50 iegūst apli. Netiek piemērots Apple ikonām, ko iOS noapaļo pats. |
zoom | vesels skaitlis, 50–400 (%) | 100 | Attēla mērogs ikonas iekšienē. Vērtības virs 100 apgriež attēlu. |
offset_x, offset_y | skaitlis, no -1 līdz 1 | 0 | Pārvieto attēlu horizontāli / vertikāli kā ikonas izmēra daļu. |
path | virkne | / | Mape jūsu serverī, kurā atradīsies ikonas. Tiek izmantota HTML fragmentā, manifestā un browserconfig. |
display | standalone | fullscreen | minimal-ui | browser | standalone | PWA attēlošanas režīms, kas tiek ierakstīts manifestā. |
pixelated | auto | 1 | 0 | auto | Asa tuvākā kaimiņa mērogošana pikseļu mākslai. auto to ieslēdz avotiem ar 64 px vai mazāk. |
maskable | 1 | 0 | 1 | Izveidot arī maskable-icon-512x512.png ar drošās zonas atkāpi Android adaptīvajām ikonām. |
ico_sizes | ar komatiem atdalīts saraksts: 16, 24, 32, 48, 64, 128, 256 | 16,32,48 | Izmēri, kas iekļauti favicon.ico. |
groups | ar komatiem atdalīts saraksts: favicon, apple, android, ms | favicon,apple,android,ms | Ģenerējamie ikonu komplekti: pārlūka favicon, Apple touch ikonas, Android / PWA ikonas un Windows flīzes. |
format | zip | json | zip | Atbildes formāts – skatiet zemāk. |
Atbilde
format=zip- Binary ZIP archive with
Content-Type: application/zipandContent-Disposition: attachment. Default. format=json- JSON object with the package
id(32 hex characters), thehtmlsnippet for your <head> and afilesarray; each file hasname,mime,size(bytes) andbase64contents.
Pieprasījuma piemērs – multipart, ZIP atbilde
curl --fail-with-body -sS https://makefav.com/api/v1/generate \
-H "Authorization: Bearer $MAKEFAV_API_KEY" \
-F "[email protected]" \
-F "app_name=My App" \
-F "theme_color=#2f9e68" \
-F "radius=20" \
-o favicons.zip HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1767225600
<binary ZIP data> Pieprasījuma piemērs – JSON ar attēla URL, JSON atbilde
curl --fail-with-body -sS https://makefav.com/api/v1/generate \
-H "Authorization: Bearer $MAKEFAV_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://example.com/logo.png",
"app_name": "My App",
"theme_color": "#2f9e68",
"radius": 20,
"groups": "favicon,apple,android",
"format": "json"
}' {
"id": "9f86d081884c7d659a2feaa0c55ad015",
"html": "<link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"/apple-icon-57x57.png\">\n…\n<meta name=\"theme-color\" content=\"#2f9e68\">",
"files": [
{"name": "favicon.ico", "mime": "image/x-icon", "size": 15086, "base64": "AAABAAMAEBAAAAEAIABoBAAANgAAACAg…"},
{"name": "favicon-16x16.png", "mime": "image/png", "size": 612, "base64": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQ…"},
{"name": "manifest.json", "mime": "application/json", "size": 1094, "base64": "ewogICAgIm5hbWUiOiAiTXkgQXBwIiwK…"}
]
}
Iegūt savu kontu
/meAtgriež lietotāju, kuram pieder API atslēga, un pašreizējo pieprasījumu limita statusu. Noderīgi atslēgas pārbaudei. Nepieciešama autentifikācija; bez parametriem.
Pieprasījuma piemērs
curl -sS https://makefav.com/api/v1/me \
-H "Authorization: Bearer $MAKEFAV_API_KEY" Atbildes piemērs
{
"id": 1,
"email": "[email protected]",
"name": "Jane Doe",
"rate_limit": {"limit": 100, "remaining": 97, "reset": 1767225600}
}
Ikonu izmēru saraksts
/sizesReturns every icon file the generator can produce, with its pixel size and group. No authentication and no parameters. The group value matches the groups parameter of POST /generate.
Pieprasījuma piemērs
curl -sS https://makefav.com/api/v1/sizes Atbildes piemērs
{
"files": [
{"name": "favicon-16x16.png", "size": 16, "group": "favicon"},
{"name": "favicon-32x32.png", "size": 32, "group": "favicon"},
{"name": "apple-touch-icon.png", "size": 180, "group": "apple"},
{"name": "android-icon-192x192.png", "size": 192, "group": "android"},
{"name": "ms-icon-144x144.png", "size": 144, "group": "ms"}
]
}
OpenAPI specifikācija
/openapi.jsonAtgriež šī API OpenAPI 3.1 aprakstu. Bez autentifikācijas. Importējiet to Postman, Insomnia vai Swagger UI, vai izmantojiet, lai ģenerētu tipizētu klientu savai valodai.
curl -sS https://makefav.com/api/v1/openapi.json -o makefav-openapi.json Kļūdas
Successful requests return HTTP 200. Every error returns a JSON body with a stable, machine-readable code and a human-readable message. Always branch on the code, not on the message text.
HTTP/1.1 422 Unprocessable Content
Content-Type: application/json
{
"error": {
"code": "invalid_image",
"message": "The uploaded file could not be decoded as an image."
}
} | HTTP statuss | Kļūdas kods | Nozīme |
|---|---|---|
| 400 | bad_request | Pieprasījums ir nepareizi veidots, piemēram, netika nosūtīts attēls vai JSON saturs ir nederīgs. |
| 401 | unauthorized | API atslēga trūkst vai ir nederīga. |
| 403 | forbidden | Atslēgas īpašnieka e-pasts nav apstiprināts, jaunumu abonements ir atspējots vai konts ir bloķēts. |
| 413 | file_too_large | Attēls ir lielāks par 10 MB. |
| 415 | unsupported_type | Faila tips vai pieprasījuma satura veids netiek atbalstīts. |
| 422 | invalid_image | Failu neizdevās atkodēt kā attēlu vai attēla URL neizdevās lejupielādēt. |
| 429 | rate_limited | Pārāk daudz pieprasījumu. Uzgaidiet līdz X-RateLimit-Reset. |
| 500 | server_error | Mūsu pusē radās kļūda. Mēģiniet vēlāk; ja problēma saglabājas, sazinieties ar atbalstu. |
Izvades faili
With all groups enabled, a package contains the files below. Files from disabled groups are left out.
| Fails | Izmērs | Grupa |
|---|---|---|
favicon.ico | 16, 32, 48 (konfigurējams) | vienmēr |
favicon-16x16.png | 16 × 16 | favicon |
favicon-32x32.png | 32 × 32 | favicon |
favicon-96x96.png | 96 × 96 | favicon |
apple-icon-57x57.png | 57 × 57 | apple |
apple-icon-60x60.png | 60 × 60 | apple |
apple-icon-72x72.png | 72 × 72 | apple |
apple-icon-76x76.png | 76 × 76 | apple |
apple-icon-114x114.png | 114 × 114 | apple |
apple-icon-120x120.png | 120 × 120 | apple |
apple-icon-144x144.png | 144 × 144 | apple |
apple-icon-152x152.png | 152 × 152 | apple |
apple-icon-180x180.png | 180 × 180 | apple |
apple-icon.png | 192 × 192 | apple |
apple-icon-precomposed.png | 192 × 192 | apple |
apple-touch-icon.png | 180 × 180 | apple |
android-icon-36x36.png | 36 × 36 | android |
android-icon-48x48.png | 48 × 48 | android |
android-icon-72x72.png | 72 × 72 | android |
android-icon-96x96.png | 96 × 96 | android |
android-icon-144x144.png | 144 × 144 | android |
android-icon-192x192.png | 192 × 192 | android |
android-icon-512x512.png | 512 × 512 | android |
web-app-manifest-192x192.png | 192 × 192 | android |
web-app-manifest-512x512.png | 512 × 512 | android |
maskable-icon-512x512.png | 512 × 512 | android |
ms-icon-70x70.png | 70 × 70 | ms |
ms-icon-144x144.png | 144 × 144 | ms |
ms-icon-150x150.png | 150 × 150 | ms |
ms-icon-310x310.png | 310 × 310 | ms |
Papildu faili
| Fails | Iekļauts | Apraksts |
|---|---|---|
favicon.svg | Tikai SVG ievadei bez apgriešanas, tālummaiņas, atkāpes, stūriem vai fona | Jūsu SVG attīrīta kopija pārlūkiem, kas atbalsta vektoru favicon. |
manifest.json, site.webmanifest | android | Tīmekļa lietotnes manifests Android un instalējamām PWA (divas identiskas kopijas). |
browserconfig.xml | ms | Windows flīžu konfigurācija ar jūsu flīžu krāsu. |
readme-makefav.txt | vienmēr | Instalēšanas instrukcijas ar HTML kodu jūsu <head> beigās. |
Koda piemēri
Each example uploads logo.png with a few options and saves favicons.zip, handling API errors. Set the environment variable MAKEFAV_API_KEY to your API key first.
Multipart augšupielāde:
# Multipart upload (recommended). --fail-with-body exits non-zero on HTTP errors
# and still saves the JSON error body, so you can inspect it.
curl --fail-with-body -sS https://makefav.com/api/v1/generate \
-H "Authorization: Bearer $MAKEFAV_API_KEY" \
-F "[email protected]" \
-F "app_name=My App" \
-F "theme_color=#2f9e68" \
-F "radius=20" \
-o favicons.zip \
|| { echo "Request failed:"; cat favicons.zip; rm -f favicons.zip; exit 1; } JSON saturs ar base64 kodētu attēlu (nepieciešams jq):
# JSON body with a base64-encoded image (built with jq to avoid argument length limits)
base64 < logo.png | tr -d '\n' > logo.b64
jq -n --rawfile img logo.b64 \
'{image_base64: $img, app_name: "My App", theme_color: "#2f9e68", radius: 20}' \
| curl --fail-with-body -sS https://makefav.com/api/v1/generate \
-H "Authorization: Bearer $MAKEFAV_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- \
-o favicons.zip \
|| { echo "Request failed:"; cat favicons.zip; rm -f favicons.zip; exit 1; } <?php
// Requires the curl extension. Run: MAKEFAV_API_KEY=mf_... php favicons.php
$apiKey = getenv('MAKEFAV_API_KEY') ?: exit("Set MAKEFAV_API_KEY first\n");
$ch = curl_init('https://makefav.com/api/v1/generate');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
CURLOPT_POSTFIELDS => [
'image' => new CURLFile('logo.png', 'image/png', 'logo.png'),
'app_name' => 'My App',
'theme_color' => '#2f9e68',
'radius' => '20',
],
]);
$body = curl_exec($ch);
if ($body === false) {
fwrite(STDERR, 'Request failed: ' . curl_error($ch) . PHP_EOL);
exit(1);
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status !== 200) {
$error = json_decode($body, true)['error'] ?? ['code' => 'http_' . $status, 'message' => substr($body, 0, 200)];
fwrite(STDERR, "Error {$status} {$error['code']}: {$error['message']}" . PHP_EOL);
exit(1);
}
file_put_contents('favicons.zip', $body);
echo 'Saved favicons.zip (' . strlen($body) . " bytes)\n"; # pip install requests · Run: MAKEFAV_API_KEY=mf_... python favicons.py
import os
import sys
import requests
API_KEY = os.environ["MAKEFAV_API_KEY"]
try:
with open("logo.png", "rb") as logo:
resp = requests.post(
"https://makefav.com/api/v1/generate",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"image": ("logo.png", logo, "image/png")},
data={"app_name": "My App", "theme_color": "#2f9e68", "radius": 20},
timeout=60,
)
except requests.RequestException as exc:
sys.exit(f"Request failed: {exc}")
if resp.status_code != 200:
try:
err = resp.json()["error"]
sys.exit(f"Error {resp.status_code} {err['code']}: {err['message']}")
except (ValueError, KeyError, TypeError):
sys.exit(f"Error {resp.status_code}: {resp.text[:200]}")
with open("favicons.zip", "wb") as out:
out.write(resp.content)
remaining = resp.headers.get("X-RateLimit-Remaining")
print(f"Saved favicons.zip ({len(resp.content)} bytes), {remaining} requests left this hour") // favicons.mjs — Node.js 18+, no dependencies. Run: MAKEFAV_API_KEY=mf_... node favicons.mjs
import { readFile, writeFile } from 'node:fs/promises';
const form = new FormData();
form.append('image', new Blob([await readFile('logo.png')], { type: 'image/png' }), 'logo.png');
form.append('app_name', 'My App');
form.append('theme_color', '#2f9e68');
form.append('radius', '20');
const res = await fetch('https://makefav.com/api/v1/generate', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.MAKEFAV_API_KEY}` },
body: form,
});
if (!res.ok) {
const body = await res.json().catch(() => null);
console.error(`Error ${res.status} ${body?.error?.code ?? ''}: ${body?.error?.message ?? res.statusText}`);
process.exit(1);
}
await writeFile('favicons.zip', Buffer.from(await res.arrayBuffer()));
console.log(`Saved favicons.zip, ${res.headers.get('x-ratelimit-remaining')} requests left this hour`); <input type="file" id="logo" accept="image/*">
<button type="button" id="go">Generate favicons</button>
<script>
// Never put your API key in browser code. Point ENDPOINT at your own backend route,
// which forwards the multipart body to https://makefav.com/api/v1/generate and adds
// the "Authorization: Bearer mf_..." header on the server.
const ENDPOINT = '/my-backend/favicons';
document.getElementById('go').addEventListener('click', async () => {
const file = document.getElementById('logo').files[0];
if (!file) {
alert('Please choose an image first.');
return;
}
const form = new FormData();
form.append('image', file);
form.append('app_name', 'My App');
form.append('theme_color', '#2f9e68');
form.append('radius', '20');
try {
const res = await fetch(ENDPOINT, { method: 'POST', body: form });
if (!res.ok) {
const body = await res.json().catch(() => null);
throw new Error(body?.error?.message || `HTTP ${res.status}`);
}
const url = URL.createObjectURL(await res.blob());
const a = Object.assign(document.createElement('a'), { href: url, download: 'favicons.zip' });
document.body.append(a);
a.click();
a.remove();
setTimeout(() => URL.revokeObjectURL(url), 1000);
} catch (err) {
alert('Favicon generation failed: ' + err.message);
}
});
</script> // go run favicons.go (MAKEFAV_API_KEY must be set)
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/textproto"
"os"
"time"
)
func main() {
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func run() error {
var body bytes.Buffer
w := multipart.NewWriter(&body)
logo, err := os.ReadFile("logo.png")
if err != nil {
return err
}
h := make(textproto.MIMEHeader)
h.Set("Content-Disposition", `form-data; name="image"; filename="logo.png"`)
h.Set("Content-Type", "image/png")
part, err := w.CreatePart(h)
if err != nil {
return err
}
if _, err := part.Write(logo); err != nil {
return err
}
for k, v := range map[string]string{"app_name": "My App", "theme_color": "#2f9e68", "radius": "20"} {
if err := w.WriteField(k, v); err != nil {
return err
}
}
if err := w.Close(); err != nil {
return err
}
req, err := http.NewRequest(http.MethodPost, "https://makefav.com/api/v1/generate", &body)
if err != nil {
return err
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("MAKEFAV_API_KEY"))
req.Header.Set("Content-Type", w.FormDataContentType())
client := &http.Client{Timeout: 60 * time.Second}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
var apiErr struct {
Error struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
_ = json.NewDecoder(resp.Body).Decode(&apiErr)
return fmt.Errorf("error %d %s: %s", resp.StatusCode, apiErr.Error.Code, apiErr.Error.Message)
}
zip, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
if err := os.WriteFile("favicons.zip", zip, 0o644); err != nil {
return err
}
fmt.Printf("Saved favicons.zip (%d bytes)\n", len(zip))
return nil
} # ruby favicons.rb (MAKEFAV_API_KEY must be set) — standard library only
require "net/http"
require "json"
require "uri"
uri = URI("https://makefav.com/api/v1/generate")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch("MAKEFAV_API_KEY")}"
res = File.open("logo.png", "rb") do |logo|
req.set_form(
[
["image", logo, { filename: "logo.png", content_type: "image/png" }],
["app_name", "My App"],
["theme_color", "#2f9e68"],
["radius", "20"]
],
"multipart/form-data"
)
Net::HTTP.start(uri.host, uri.port, use_ssl: true, read_timeout: 60) { |http| http.request(req) }
end
unless res.is_a?(Net::HTTPSuccess)
err = (JSON.parse(res.body)["error"] rescue nil) || { "code" => res.code, "message" => res.body.to_s[0, 200] }
abort "Error #{res.code} #{err["code"]}: #{err["message"]}"
end
File.binwrite("favicons.zip", res.body)
puts "Saved favicons.zip (#{res.body.bytesize} bytes)" // .NET 6+ console app (Program.cs, top-level statements, implicit usings enabled)
using System.Net.Http.Headers;
using System.Text.Json;
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(60) };
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("MAKEFAV_API_KEY"));
using var form = new MultipartFormDataContent();
var image = new ByteArrayContent(await File.ReadAllBytesAsync("logo.png"));
image.Headers.ContentType = new MediaTypeHeaderValue("image/png");
form.Add(image, "image", "logo.png");
form.Add(new StringContent("My App"), "app_name");
form.Add(new StringContent("#2f9e68"), "theme_color");
form.Add(new StringContent("20"), "radius");
using var response = await http.PostAsync("https://makefav.com/api/v1/generate", form);
if (!response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync();
string code = "", message = body;
try
{
var error = JsonDocument.Parse(body).RootElement.GetProperty("error");
code = error.GetProperty("code").GetString() ?? "";
message = error.GetProperty("message").GetString() ?? "";
}
catch (Exception e) when (e is JsonException or KeyNotFoundException or InvalidOperationException) { }
Console.Error.WriteLine($"Error {(int)response.StatusCode} {code}: {message}");
return 1;
}
await File.WriteAllBytesAsync("favicons.zip", await response.Content.ReadAsByteArrayAsync());
Console.WriteLine("Saved favicons.zip");
return 0; // Java 11+, no dependencies. Run: MAKEFAV_API_KEY=mf_... java MakeFav.java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
public class MakeFav {
public static void main(String[] args) throws IOException, InterruptedException {
String boundary = "----MakeFav" + UUID.randomUUID().toString().replace("-", "");
Map<String, String> fields = new LinkedHashMap<>();
fields.put("app_name", "My App");
fields.put("theme_color", "#2f9e68");
fields.put("radius", "20");
// Build the multipart/form-data body by hand
ByteArrayOutputStream body = new ByteArrayOutputStream();
for (Map.Entry<String, String> field : fields.entrySet()) {
body.write(("--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"" + field.getKey() + "\"\r\n\r\n"
+ field.getValue() + "\r\n").getBytes(StandardCharsets.UTF_8));
}
body.write(("--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"image\"; filename=\"logo.png\"\r\n"
+ "Content-Type: image/png\r\n\r\n").getBytes(StandardCharsets.UTF_8));
body.write(Files.readAllBytes(Path.of("logo.png")));
body.write(("\r\n--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8));
HttpRequest request = HttpRequest.newBuilder(URI.create("https://makefav.com/api/v1/generate"))
.timeout(Duration.ofSeconds(60))
.header("Authorization", "Bearer " + System.getenv("MAKEFAV_API_KEY"))
.header("Content-Type", "multipart/form-data; boundary=" + boundary)
.POST(HttpRequest.BodyPublishers.ofByteArray(body.toByteArray()))
.build();
HttpResponse<byte[]> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofByteArray());
if (response.statusCode() != 200) {
// Error body is JSON: {"error":{"code":"...","message":"..."}}
System.err.println("Error " + response.statusCode() + ": "
+ new String(response.body(), StandardCharsets.UTF_8));
System.exit(1);
}
Files.write(Path.of("favicons.zip"), response.body());
System.out.println("Saved favicons.zip (" + response.body().length + " bytes)");
}
} GitHub Actions darbplūsma – JSON formāts, faili atkodēti ar jq:
# .github/workflows/favicons.yml — regenerate favicons whenever the logo changes.
# Add your key as a repository secret named MAKEFAV_API_KEY.
name: Favicons
on:
push:
paths: ['branding/logo.png']
workflow_dispatch:
jobs:
favicons:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generate favicon package (JSON format)
env:
MAKEFAV_API_KEY: ${{ secrets.MAKEFAV_API_KEY }}
run: |
set -euo pipefail
curl --fail-with-body -sS https://makefav.com/api/v1/generate \
-H "Authorization: Bearer $MAKEFAV_API_KEY" \
-F "image=@branding/logo.png" \
-F "app_name=My App" \
-F "theme_color=#2f9e68" \
-F "radius=20" \
-F "path=/icons/" \
-F "format=json" \
-o favicons.json || { cat favicons.json; exit 1; }
mkdir -p public/icons
# Decode every file from the JSON response (jq is preinstalled on GitHub runners)
jq -r '.files[] | "\(.name) \(.base64)"' favicons.json |
while read -r name data; do
printf '%s' "$data" | base64 -d > "public/icons/$(basename "$name")"
done
jq -r '.html' favicons.json > public/icons/head-snippet.html
ls -l public/icons
- uses: actions/upload-artifact@v4
with:
name: favicons
path: public/icons Vienkāršs shell skripts jebkuram CI – ZIP formāts:
#!/usr/bin/env bash
# scripts/favicons.sh — simpler variant for any CI or build step: fetch the ZIP and unpack it.
set -euo pipefail
: "${MAKEFAV_API_KEY:?Set MAKEFAV_API_KEY}"
curl --fail-with-body -sS https://makefav.com/api/v1/generate \
-H "Authorization: Bearer $MAKEFAV_API_KEY" \
-F "[email protected]" \
-F "app_name=My App" \
-F "theme_color=#2f9e68" \
-F "radius=20" \
-o favicons.zip || { cat favicons.zip; rm -f favicons.zip; exit 1; }
unzip -o -q favicons.zip -d public/
rm favicons.zip
echo "Favicons written to public/" HTML lietošana
Upload all files to the folder you set with path, then paste the snippet into the <head> of every page. It is included at the end of readme-makefav.txt in the package and, with format=json, returned in the html field. Example for the options used in the code examples above:
<head>
<meta charset="utf-8">
<title>My App</title>
<link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="manifest" href="/manifest.json">
<meta name="msapplication-TileColor" content="#2f9e68">
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
<meta name="msapplication-config" content="/browserconfig.xml">
<meta name="theme-color" content="#2f9e68">
</head> Pēc izvietošanas notīriet pārlūka kešatmiņu vai atveriet vietni privātajā logā – pārlūki favicon kešo ļoti agresīvi.
Izmaiņu žurnāls
v1
- MakeFav REST API pirmā publiskā versija.
- Endpoints
POST /generate,GET /me,GET /sizesandGET /openapi.json. - ZIP un JSON atbildes formāti, multipart, base64 un URL attēla ievade.
- Personiskās API atslēgas ar 100 pieprasījumiem stundā.
1. versija ir stabila: mēs pievienojam tikai neobligātus parametrus un laukus. Izmaiņas, kas pārtrauc saderību, tiks izlaistas kā jauna versija ar iepriekšēju paziņojumu.
Atbalsts
Jautājumi, kļūdu ziņojumi vai nepieciešams augstāks pieprasījumu limits? Mēs labprāt palīdzēsim. Lūdzu, ziņojumā norādiet pieprasījuma laiku un kļūdas kodu – nekādā gadījumā ne savu API atslēgu.