CodeBlanks Logo Icon CodeBlanks
Geliştiriciler

CodeBlanks'i kendi ürününe bağla

Kullanıcılarını CodeBlanks hesabıyla giriş yaptır, öğrenme ilerlemelerini (XP, rozet, sertifika) API ile oku, olayları webhook ile anında al.

Giriş yap ve başla

Genel bakış

Üç yol var; ihtiyacına göre birini ya da hepsini kullan:

"CodeBlanks ile giriş": kullanıcılar senin sitende CodeBlanks hesabıyla oturum açar (OAuth 2.0 + OpenID Connect).
API: profil, XP, rozet ve sertifika verisini JSON olarak okursun.
Webhook'lar: bir kullanıcı rozet kazandığında ya da kurs bitirdiğinde sunucuna bildirim gelir.

Kimlik doğrulama

Her istekte Authorization başlığında bir kimlik gönder. İki tür kimlik geçerli:

  • Kişisel API anahtarı (cbk_ ile başlar): Panel > Geliştirici bölümünden oluşturulur, kendi hesabının verisini okur.
  • OAuth erişim token'ı: "CodeBlanks ile giriş" ile alınır, izin veren kullanıcının verisini, verdiği kapsamlar kadar okur.
curl -H "Authorization: Bearer cbk_…" https://codeblanks.com/api/v1/me

Anahtarları ve secret'ları yalnızca sunucuda tut; tarayıcıya ya da mobil uygulama paketine koyma.

Kapsamlar

Bir anahtar ya da token yalnızca sahip olduğu kapsamların uç noktalarını çağırabilir.

  • profile: ad, kullanıcı adı, avatar, profil bağlantısı, XP
  • email: e-posta adresi
  • progress: XP, rütbe, seri, rozetler, sertifikalar

Uç noktalar

Tüm uç noktalar salt okunur (GET) ve JSON döner. Başarılı yanıt "data", hata "error" alanında gelir. ?lang=tr|en ile rozet ve rütbe adlarının dilini seçebilirsin.

https://codeblanks.com/api/v1

İstek Kapsam Açıklama
GET /me profile Giriş yapan kullanıcının profili. email kapsamı varsa e-posta da gelir.
GET /me/progress progress XP, rütbe, seri, tamamlanan kurs sayısı, rozetler ve sertifikalar.
GET /users/{username} profile Herhangi bir kullanıcının herkese açık profili.
GET /users/{username}/badges profile Kullanıcının kazandığı rozetler.
GET /certificates/{code} herhangi Sertifika doğrulama: kod geçerliyse sahibi ve kursu döner.

Örnek istek

curl -H "Authorization: Bearer cbk_…" "https://codeblanks.com/api/v1/me/progress?lang=tr"

Örnek yanıt

{
  "data": {
    "xp": 1840,
    "rank": {
      "current": { "id": 3, "name": "Kod Çırağı", "min_xp": 1000 },
      "next": { "id": 4, "name": "Geliştirici", "min_xp": 2500 }
    },
    "streak": { "current": 6, "longest": 21, "last_activity": "2026-10-13" },
    "courses_completed": 2,
    "badges": [
      { "id": 12, "key": "lessons_completed_10", "name": "10 ders", "icon": "fas fa-book", "color": "#0D9488", "xp_reward": 50, "earned_at": "2026-10-02T14:11:09+03:00" }
    ],
    "certificates": [
      { "code": "CB-1A2B-3C4D-5E6F", "course_id": 4, "course_title": "PHP Temelleri", "issued_at": "2026-09-28T10:00:00+03:00", "verify_url": "https://codeblanks.com/api/v1/certificates/CB-1A2B-3C4D-5E6F" }
    ]
  }
}

Hız sınırı ve hatalar

Anahtar / token başına dakikada 60 istek. Her yanıtta X-RateLimit-Limit, X-RateLimit-Remaining ve X-RateLimit-Reset başlıkları gelir; sınır aşılınca 429 ve Retry-After döner.

401 Kimlik yok, geçersiz, süresi dolmuş ya da iptal edilmiş.
403 Kapsam yetersiz (insufficient_scope) ya da hesap askıya alınmış.
404 Kullanıcı, sertifika ya da uç nokta bulunamadı.
429 Hız sınırı aşıldı.
503 API geçici olarak kapalı.
{ "error": { "code": "insufficient_scope", "message": "This credential does not have the \"progress\" scope." } }

"CodeBlanks ile giriş" ekle

Standart OAuth 2.0 yetki kodu akışı + PKCE (S256, zorunlu) + OpenID Connect. Hazır bir OAuth / OIDC kütüphanesi keşif adresini vermen yeterli olacak şekilde çalışır.

  1. Panel > Geliştirici > Uygulamalarım bölümünden uygulama oluştur; client_id ve client secret'ı al, dönüş adresini kaydet.
  2. Kullanıcıyı yetki adresine gönder (response_type=code, client_id, redirect_uri, scope, state, code_challenge, code_challenge_method=S256).
  3. Kullanıcı onaylayınca dönüş adresine ?code=…&state=… ile gelir; state'i doğrula.
  4. Kodu sunucundan token adresine gönder (grant_type=authorization_code, code, redirect_uri, code_verifier, client kimliği). access_token, refresh_token ve id_token gelir.
  5. id_token'ı JWKS ile doğrula ya da access_token ile userinfo / API çağır. Kullanıcıyı "sub" (CodeBlanks kullanıcı kimliği) ile eşleştir.

Adresler

Keşif belgesi https://codeblanks.com/.well-known/openid-configuration
Yetki https://codeblanks.com/oauth/authorize
Token POST https://codeblanks.com/oauth/token
Kullanıcı bilgisi https://codeblanks.com/oauth/userinfo
İmza anahtarları (JWKS) https://codeblanks.com/oauth/jwks.json
Token iptali POST https://codeblanks.com/oauth/revoke

Erişim token'ı 1 saat, yenileme token'ı 30 gün geçerli. Yenileme token'ı her kullanımda değişir; eskisi tekrar kullanılırsa o oturumun tüm token'ları iptal edilir.

PHP örneği (league/oauth2-client)

$provider = new \League\OAuth2\Client\Provider\GenericProvider([
    'clientId'                => 'cb_…',
    'clientSecret'            => 'cbs_…',
    'redirectUri'             => 'https://liyakat.net/auth/codeblanks/callback',
    'urlAuthorize'            => 'https://codeblanks.com/oauth/authorize',
    'urlAccessToken'          => 'https://codeblanks.com/oauth/token',
    'urlResourceOwnerDetails' => 'https://codeblanks.com/oauth/userinfo',
    'scopes'                  => 'openid profile email progress',
    'scopeSeparator'          => ' ',
    'pkceMethod'              => \League\OAuth2\Client\Provider\GenericProvider::PKCE_METHOD_S256,
]);

// 1) Giriş düğmesi
if (!isset($_GET['code'])) {
    $url = $provider->getAuthorizationUrl();
    $_SESSION['oauth2state'] = $provider->getState();
    $_SESSION['oauth2pkce']  = $provider->getPkceCode();
    header('Location: ' . $url);
    exit;
}

// 2) Dönüş
if (!hash_equals($_SESSION['oauth2state'] ?? '', $_GET['state'] ?? '')) {
    exit('Invalid state');
}
$provider->setPkceCode($_SESSION['oauth2pkce']);
$token = $provider->getAccessToken('authorization_code', ['code' => $_GET['code']]);
$user  = $provider->getResourceOwner($token)->toArray(); // sub, preferred_username, name, email …

// 3) API: XP ve rozetler
$req = $provider->getAuthenticatedRequest('GET', 'https://codeblanks.com/api/v1/me/progress', $token);
$progress = json_decode((string) $provider->getResponse($req)->getBody(), true)['data'];

Webhook'lar

Panel > Geliştirici > Webhook'lar bölümünden adres ve olayları seç. Kişisel webhook yalnızca senin olaylarını alır; uygulamana bağlı webhook, uygulamana "progress" izni veren tüm kullanıcıların olaylarını alır.

Olaylar

badge.earned Rozet kazanıldı progress
course.completed Kurs tamamlandı progress
certificate.issued Sertifika verildi progress
rank.changed Rütbe atlandı progress

Başlıklar

POST /webhooks/codeblanks HTTP/1.1
Content-Type: application/json
User-Agent: CodeBlanks-Webhooks/1.0
X-CodeBlanks-Event: badge.earned
X-CodeBlanks-Delivery: 9f0c…
X-CodeBlanks-Signature: t=1791880000,v1=5d41402abc4b2a76b9719d911017c592…

Gövde

{
  "id": "evt_9f0c2b7e4d1a4c0b8e6f3a2d1c0b9a87",
  "type": "badge.earned",
  "created": 1791880000,
  "data": {
    "user": { "id": 42, "username": "murat", "profile_url": "https://codeblanks.com/@murat" },
    "badge": { "id": 12, "key": "lessons_completed_10", "name": "10 ders", "icon": "fas fa-book", "xp_reward": 50 }
  }
}

İmzayı doğrula

X-CodeBlanks-Signature başlığı t=<zaman>,v1=<imza> biçimindedir. imza = HMAC-SHA256(imza anahtarı, "<t>.<ham gövde>"). Zamanı 5 dakikadan eskiyse isteği reddet; aynı X-CodeBlanks-Delivery'yi ikinci kez işleme.

$body   = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_CODEBLANKS_SIGNATURE'] ?? '';
parse_str(str_replace(',', '&', $header), $sig);           // ['t' => …, 'v1' => …]
$expected = hash_hmac('sha256', ($sig['t'] ?? '') . '.' . $body, getenv('CODEBLANKS_WEBHOOK_SECRET'));

if (!hash_equals($expected, $sig['v1'] ?? '') || abs(time() - (int) ($sig['t'] ?? 0)) > 300) {
    http_response_code(400);
    exit;
}
http_response_code(204);                                   // hemen dön, işi kuyruğa at
$event = json_decode($body, true);
// Node.js (Express): gövdeyi ham haliyle al
app.post('/webhooks/codeblanks', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = Object.fromEntries(req.get('X-CodeBlanks-Signature').split(',').map(p => p.split('=')));
  const expected = crypto.createHmac('sha256', process.env.CODEBLANKS_WEBHOOK_SECRET)
    .update(sig.t + '.' + req.body).digest('hex');
  const a = Buffer.from(expected), b = Buffer.from(sig.v1 || '');
  const ok = a.length === b.length && crypto.timingSafeEqual(a, b);
  if (!ok || Math.abs(Date.now() / 1000 - Number(sig.t)) > 300) return res.sendStatus(400);
  res.sendStatus(204);
  const event = JSON.parse(req.body);
});

2xx dışında bir yanıt ya da zaman aşımı (5 sn) başarısız sayılır ve tekrar denenir: 1 dk, 5 dk, 30 dk, 2 sa, 6 sa, 24 sa. Art arda çok başarısız teslim olursa webhook kapanır. Hemen 2xx dön, işi arka planda yap.

Destek

Soru ya da hata bildirimi için iletişim sayfasını kullan. İletişim