Lewati ke konten utama

Blog Articles API — Dokumentasi

Versi: 1.0 • Terakhir diperbarui: 2025-11-05 04:19:30 (Asia/Jakarta)
Host API: https://api-sjs.bizpro.my.id
Resource Base Path (diasumsikan): /blog_articles

Catatan: Blueprint blog_articles_bp = Blueprint('blog_articles', __name__) tidak mendefinisikan url_prefix. Dokumentasi ini mengasumsikan blueprint dipasang pada path dasar /blog_articles. Jika berbeda di aplikasi Anda, sesuaikan contoh URL di bawah.


Ringkasan​

API ini mengelola artikel blog dengan dukungan unggah gambar (multipart form) dan metadata lengkap (slug, excerpt, content, author, category, tags, dsb.).

Fitur utama

  • CRUD artikel (list, get by id, create, update, delete)
  • Upload file gambar via field image_file (multipart/form-data)
  • Alternatif: gunakan image_url bila file tidak diunggah
  • Slug otomatis dari title jika tidak dikirim
  • tags aman diparse dengan json.loads (fallback daftar dipisah koma)
  • Pembersihan file lama saat update/delete (bila host sesuai domain API)
  • Kolom published_at dapat dikirim manual atau default UTC now di server

Konvensi respons

  • Sukses: { "success": true, ... }
  • Gagal: { "success": false, "message": "..." }

Skema Tabel​

Nama tabel: blog_articles

KolomTipeKeterangan
idINT UNSIGNED (PK)Auto increment
titleVARCHAR(255)Wajib
slugVARCHAR(255) UNIQUEDefault: dari title (lower().replace(' ', '-')) jika tidak dikirim
excerptTEXTRingkasan (opsional)
contentLONGTEXTKonten HTML/Markdown (opsional)
image_urlVARCHAR(255)URL gambar (opsional; diisi saat upload sukses)
image_altVARCHAR(255)Alt text (opsional)
authorVARCHAR(100)Nama penulis (opsional)
published_atDATETIMEWaktu terbit (opsional)
is_featuredTINYINT(1)1=unggulan; default 0
is_activeTINYINT(1)1=aktif; default 1
created_atDATETIMEOtomatis oleh DB
updated_atDATETIMEOtomatis on update
detail_urlVARCHAR(255)Link detail (opsional)
category_idINTFK ke blog_categories.id (opsional)
tagsLONGTEXT (JSON valid)Disarankan JSON array string; DB memeriksa json_valid(tags)

Penyimpanan file gambar

  • Folder: Config.UPLOAD_FOLDER_ARTICLES (default public/img/articles)
  • Nama file: uuid4.ext (aman dengan secure_filename)
  • URL publik dibentuk: https://api-sjs.bizpro.my.id/public/img/articles/<uuid>.<ext>

Format tags

  • Kirim sebagai JSON string: ["hr", "outsourcing"]
  • Jika mengirim string biasa "hr, outsourcing", server akan fallback memisah koma.

Keamanan parsing

  • Tidak menggunakan eval() untuk tags; menggunakan json.loads() (aman).

Endpoints​

1) List semua artikel​

GET https://api-sjs.bizpro.my.id/blog_articles/

Respons 200

{ "success": true, "data": [ /* array artikel */ ] }

Respons 500

{ "success": false, "message": "penjelasan kesalahan" }

2) Ambil artikel berdasarkan ID​

GET https://api-sjs.bizpro.my.id/blog_articles/{id}

Respons 200

{ "success": true, "data": { /* objek artikel */ } }

Respons 404

{ "success": false, "message": "Not found" }

Respons 500

{ "success": false, "message": "penjelasan kesalahan" }

3) Buat artikel baru (multipart form)​

POST https://api-sjs.bizpro.my.id/blog_articles/

Tipe konten: multipart/form-data

Field Form (teks)

  • title (string, wajib)
  • slug (string, opsional; default dari title)
  • excerpt (string, opsional)
  • content (string, opsional)
  • image_alt (string, opsional)
  • author (string, opsional)
  • published_at (string datetime, opsional; default UTC now)
  • is_featured (0/1, opsional; default 0)
  • is_active (0/1, opsional; default 1)
  • detail_url (string, opsional)
  • category_id (int, opsional)
  • tags (string JSON atau daftar dipisah koma; opsional)

Field File (opsional)

  • image_file (png/jpg/jpeg/gif/webp; maksimal sesuai konfigurasi server)

Alternatif tanpa upload file

  • Kirim image_url (string) sebagai URL gambar publik.

Contoh (upload file)

curl -s -X POST "https://api-sjs.bizpro.my.id/blog_articles/"   -H "Accept: application/json"   -F "title=Tips Rekrutmen Efisien"   -F "excerpt=Ringkasan singkat artikel"   -F "content=<h1>Konten</h1><p>...</p>"   -F "author=SJS Team"   -F "is_active=1"   -F "is_featured=1"   -F "tags=[\"rekrutmen\", \"outsourcing\"]"   -F "image_file=@/path/to/image.webp"

Contoh (pakai image_url)

curl -s -X POST "https://api-sjs.bizpro.my.id/blog_articles/"   -H "Accept: application/json"   -F "title=Panduan HR 2025"   -F "image_url=https://cdn.example.com/img/hr2025.jpg"   -F "tags=hr, panduan"

Respons 201

{ "success": true, "id": 38, "message": "Article created successfully" }

Respons 400

{ "success": false, "message": "Title is required" }

Respons 500

{ "success": false, "message": "penjelasan kesalahan" }

4) Perbarui artikel (multipart form)​

PUT https://api-sjs.bizpro.my.id/blog_articles/{id}

Tipe konten: multipart/form-data

Catatan penting

  • title tetap wajib pada update.
  • Jika mengunggah image_file baru dan image_url lama berasal dari domain API, file lama akan dihapus dari storage.
  • Jika tidak mengunggah file, Anda bisa mengirim image_url baru untuk mengganti tautan gambar.

Contoh (ganti sebagian field + upload gambar baru)

curl -s -X PUT "https://api-sjs.bizpro.my.id/blog_articles/38"   -H "Accept: application/json"   -F "title=Tips Rekrutmen Efisien (Update)"   -F "is_featured=0"   -F "tags=[\"rekrutmen\", \"hr\"]"   -F "image_file=@/path/to/new-image.jpg"

Contoh (tanpa upload, ganti image_url)

curl -s -X PUT "https://api-sjs.bizpro.my.id/blog_articles/38"   -H "Accept: application/json"   -F "title=Panduan HR 2025 (Update)"   -F "image_url=https://cdn.example.com/img/hr2025-new.jpg"

Respons 200

{ "success": true, "affected": 1, "message": "Article updated successfully" }

Respons 404

{ "success": false, "message": "Not found" }

Respons 400

{ "success": false, "message": "Title is required" }

Respons 500

{ "success": false, "message": "penjelasan kesalahan" }

5) Hapus artikel​

DELETE https://api-sjs.bizpro.my.id/blog_articles/{id}

Perilaku tambahan

  • Jika image_url adalah URL di domain API (folder upload default), server mencoba menghapus file terkait.

Contoh

curl -s -X DELETE "https://api-sjs.bizpro.my.id/blog_articles/38"

Respons 200

{ "success": true, "affected": 1, "message": "Article deleted successfully" }

Respons 404

{ "success": false, "message": "Not found" }

Respons 500

{ "success": false, "message": "penjelasan kesalahan" }

Validasi & Batasan​

  • File type: png, jpg, jpeg, gif, webp (field image_file) — divalidasi oleh allowed_file().
  • Slug: wajib unik di DB (index unik). Jika mengirim slug duplikat, insert/update dari layer model akan gagal (tangani pesan error).
  • Tags: simpan sebagai JSON valid. Pastikan aplikasi frontend mengirim JSON string atau string dipisah koma dengan benar.
  • Category: category_id adalah FK ke blog_categories.id (pastikan id valid).

Praktik Terbaik Produksi​

  • Batasi ukuran file upload di konfigurasi server (Nginx/Flask) dan validasi ukuran di aplikasi.
  • Tambahkan auth (JWT/session) & rate limiting.
  • Logging terstruktur untuk audit (request-id, user-id).
  • Jika arsitektur CDN, simpan hanya path relatif pada DB, dan bangun URL publik di frontend.
  • Sanitasi konten content bila HTML (hindari XSS).

Changelog​

  • v1.0 — Dokumentasi awal berdasarkan blog_articles_routes.py dan skema blog_articles.