MakeFav API belgeleri
Kendi kodunuzdan, derleme betiklerinizden ve CI hatlarınızdan eksiksiz favicon paketleri oluşturun. Tek bir istek, herhangi bir görseli favicon.ico, Apple touch icon'lar, Android ve PWA simgeleri, bir web manifestosu ve yapıştırmaya hazır HTML koduna dönüştürür.
Bu sayfada
Hızlı başlangıç
MakeFav API, basit bir HTTPS + JSON REST API'sidir. Tüm uç noktalar tek bir temel URL altında bulunur:
https://makefav.com/api/v1 - Ücretsiz hesap oluşturun
Kaydolun, e-posta adresinizi doğrulayın ve MakeFav bülten aboneliğinizi aktif tutun – ücretsiz planın tek şartı budur. - API anahtarı oluşturun
Hesabınızdaki API anahtarları sayfasını açın ve kişisel bir anahtar oluşturun. Anahtar mf_ ile başlar ve yalnızca bir kez gösterilir, bu yüzden güvenli bir yerde saklayın. API anahtarlarını yönet - İlk isteğinizi gönderin
Generate uç noktasına bir görsel yükleyin ve dönen ZIP dosyasını kaydedin:
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.
Kimlik doğrulama
Korumalı bir uç noktaya yapılan her istek kişisel bir API anahtarı içermelidir. Anahtarları istediğiniz zaman hesap sayfanızdan oluşturabilir, adlandırabilir ve iptal edebilirsiniz: API anahtarları
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.
İstek sınırları
Varsayılan olarak her API anahtarı saatte 100 istek yapabilir. Kimliği doğrulanmış her yanıt, mevcut durumunuzu bildirir:
| Başlık | Açıklama |
|---|---|
X-RateLimit-Limit | Geçerli pencerede izin verilen maksimum istek sayısı. |
X-RateLimit-Remaining | Geçerli pencerede kalan istek sayısı. |
X-RateLimit-Reset | Pencerenin sıfırlanacağı Unix zaman damgası (saniye, UTC). |
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.
Uç noktalar
| Uç nokta | Kimlik doğrulama | Açıklama |
|---|---|---|
POST /generate | API anahtarı | Eksiksiz bir favicon paketi oluşturur. |
GET /me | API anahtarı | Hesabınız ve geçerli istek sınırı durumu. |
GET /sizes | Yok | Oluşturucunun ürettiği tüm simge dosyalarının ve boyutlarının listesi. |
GET /openapi.json | Yok | Makine tarafından okunabilir OpenAPI 3.1 spesifikasyonu. |
Favicon paketi oluştur
/generateTek bir kaynak görselden eksiksiz bir favicon paketi oluşturur. Görseli üç yoldan biriyle gönderebilirsiniz:
| İçerik türü | Görsel alanı | Açıklama |
|---|---|---|
multipart/form-data | image | Dosya yükleme. Önerilir – en verimli seçenek. |
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 | Görselin herkese açık http veya https URL'si. Sunucu görseli indirir (en fazla 10 MB). |
Desteklenen giriş biçimleri: PNG, JPG, WebP, AVIF, GIF, BMP, SVG ve ICO. Maksimum dosya boyutu: 10 MB.
Parametreler
Tüm parametreler isteğe bağlıdır. Bunları form alanları (multipart) veya JSON özellikleri olarak gönderin. Geçersiz değerler varsayılana döner.
| Ad | Tür / aralık | Varsayılan | Açıklama |
|---|---|---|---|
app_name | dize, en fazla 60 karakter | My Website | Web sitenizin veya uygulamanızın adı; manifest.json dosyasında ve örnek sayfada kullanılır. |
short_name | dize, en fazla 24 karakter | app_name değerinin ilk 12 karakteri | Android ana ekranlarında simgenin altında gösterilen kısa ad. |
theme_color | #rrggbb | #ffffff | Tarayıcı arayüz rengi (theme-color meta etiketi ve manifest). |
tile_color | #rrggbb | theme_color ile aynı | Windows Başlat kutucuklarının arka plan rengi. |
background | transparent | #rrggbb | transparent | Tarayıcı, Android ve Windows simgelerinin arka planı. |
apple_background | #rrggbb | #ffffff | Apple touch simgelerinin ve maskable simgenin arka planı (iOS saydamlığı desteklemez). Arka plan bir renkse yok sayılır; bunun yerine o renk kullanılır. |
padding | tam sayı, 0–40 (%) | 0 | Görselin çevresindeki boşluk, simge boyutunun yüzdesi olarak. |
radius | tam sayı, 0–50 (%) | 0 | Yuvarlatılmış köşeler. 50 daire oluşturur. iOS'un kendisinin yuvarlattığı Apple simgelerine uygulanmaz. |
zoom | tam sayı, 50–400 (%) | 100 | Görselin simge içindeki ölçeği. 100'ün üzerindeki değerler görseli kırpar. |
offset_x, offset_y | sayı, -1 ile 1 arası | 0 | Görseli yatay / dikey olarak, simge boyutunun bir oranı kadar kaydırır. |
path | dize | / | Simgelerin bulunacağı sunucunuzdaki klasör. HTML kod parçasında, manifest ve browserconfig dosyasında kullanılır. |
display | standalone | fullscreen | minimal-ui | browser | standalone | Manifest'e yazılan PWA görüntüleme modu. |
pixelated | auto | 1 | 0 | auto | Piksel sanat için keskin en yakın komşu ölçekleme. auto, 64 px veya daha küçük kaynaklarda bunu etkinleştirir. |
maskable | 1 | 0 | 1 | Android uyarlanabilir simgeler için güvenli alan dolgulu maskable-icon-512x512.png dosyasını da oluşturur. |
ico_sizes | virgülle ayrılmış 16, 24, 32, 48, 64, 128, 256 listesi | 16,32,48 | favicon.ico içine gömülen boyutlar. |
groups | virgülle ayrılmış favicon, apple, android, ms listesi | favicon,apple,android,ms | Oluşturulacak simge setleri: tarayıcı faviconları, Apple touch simgeleri, Android / PWA simgeleri ve Windows kutucukları. |
format | zip | json | zip | Yanıt biçimi – aşağıya bakın. |
Yanıt
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.
Örnek istek – multipart, ZIP yanıtı
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> Örnek istek – görsel URL'li JSON, JSON yanıtı
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…"}
]
}
Hesabınızı alın
/meAPI anahtarının ait olduğu kullanıcıyı ve mevcut istek sınırı durumunu döndürür. Bir anahtarı doğrulamak için kullanışlıdır. Kimlik doğrulama gerektirir; parametre yoktur.
Örnek istek
curl -sS https://makefav.com/api/v1/me \
-H "Authorization: Bearer $MAKEFAV_API_KEY" Örnek yanıt
{
"id": 1,
"email": "[email protected]",
"name": "Jane Doe",
"rate_limit": {"limit": 100, "remaining": 97, "reset": 1767225600}
}
Simge boyutlarını listele
/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.
Örnek istek
curl -sS https://makefav.com/api/v1/sizes Örnek yanıt
{
"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 spesifikasyonu
/openapi.jsonBu API'nin OpenAPI 3.1 tanımını döndürür. Kimlik doğrulama gerekmez. Postman, Insomnia veya Swagger UI'a aktarın ya da kendi dilinize uygun türlü bir istemci oluşturmak için kullanın.
curl -sS https://makefav.com/api/v1/openapi.json -o makefav-openapi.json Hatalar
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 durumu | Hata kodu | Anlamı |
|---|---|---|
| 400 | bad_request | İstek hatalı biçimlendirilmiş; örneğin görsel gönderilmedi veya JSON gövdesi geçersiz. |
| 401 | unauthorized | API anahtarı eksik veya geçersiz. |
| 403 | forbidden | Anahtar sahibinin e-postası doğrulanmamış, bülten aboneliği devre dışı veya hesap yasaklanmış. |
| 413 | file_too_large | Görsel 10 MB'tan büyük. |
| 415 | unsupported_type | Dosya türü veya istek içerik türü desteklenmiyor. |
| 422 | invalid_image | Dosya görsel olarak çözümlenemedi veya görsel URL'si indirilemedi. |
| 429 | rate_limited | Çok fazla istek. X-RateLimit-Reset zamanına kadar bekleyin. |
| 500 | server_error | Bizim tarafımızda bir sorun oluştu. Daha sonra tekrar deneyin; sorun devam ederse destekle iletişime geçin. |
Çıktı dosyaları
With all groups enabled, a package contains the files below. Files from disabled groups are left out.
| Dosya | Boyut | Grup |
|---|---|---|
favicon.ico | 16, 32, 48 (yapılandırılabilir) | her zaman |
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 |
Ek dosyalar
| Dosya | Dahil | Açıklama |
|---|---|---|
favicon.svg | Yalnızca kırpma, yakınlaştırma, dolgu, köşe veya arka plan içermeyen SVG girişi için | Vektör faviconları destekleyen tarayıcılar için SVG dosyanızın temizlenmiş kopyası. |
manifest.json, site.webmanifest | android | Android ve yüklenebilir PWA'lar için web uygulaması manifest'i (iki aynı kopya). |
browserconfig.xml | ms | Kutucuk renginizi içeren Windows kutucuk yapılandırması. |
readme-makefav.txt | her zaman | Sonunda <head> bölümünüz için HTML kodunu içeren kurulum talimatları. |
Kod örnekleri
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 yükleme:
# 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; } Base64 kodlu görsel içeren JSON gövdesi (jq gerektirir):
# 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 iş akışı – JSON biçimi, dosyalar jq ile çözülür:
# .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 Herhangi bir CI için basit kabuk betiği – ZIP biçimi:
#!/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 kullanımı
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> Yayına aldıktan sonra tarayıcı önbelleğinizi temizleyin veya siteyi gizli pencerede açın – tarayıcılar faviconları agresif şekilde önbelleğe alır.
Değişiklik günlüğü
v1
- MakeFav REST API'nin ilk herkese açık sürümü.
- Endpoints
POST /generate,GET /me,GET /sizesandGET /openapi.json. - ZIP ve JSON yanıt biçimleri; multipart, base64 ve URL ile görsel girişi.
- Saatte 100 istek hakkı olan kişisel API anahtarları.
Sürüm 1 kararlıdır: yalnızca isteğe bağlı parametreler ve alanlar ekleriz. Geriye dönük uyumsuz değişiklikler önceden duyurularak yeni bir sürüm olarak yayınlanır.
Destek
Sorularınız, hata bildirimleriniz mi var ya da daha yüksek bir istek sınırına mı ihtiyacınız var? Yardımcı olmaktan memnuniyet duyarız. Lütfen mesajınıza istek zamanını ve hata kodunu ekleyin – API anahtarınızı asla eklemeyin.