meme-backend / docs /API_REFERENCE.md
shaileshrv1432's picture
Upload 64 files
d70a48e verified
|
Raw
History Blame Contribute Delete
9.39 kB

API Reference

Base URL (production): https://shaileshrv1432-meme-backend.hf.space Local: http://localhost:8000

Interactive docs are served live by the running app:

  • RapiDoc β€” /docs
  • ReDoc β€” /redoc

Conventions

  • Auth: endpoints marked πŸ”’ require a header Authorization: Bearer <access_token>.
  • Admin: endpoints marked πŸ›‘ require header X-Admin-Secret: <ADMIN_SECRET> and return 404 when APP_ENV=production.
  • Body type: most write endpoints take application/x-www-form-urlencoded (Form(...)). A few take JSON (Body(...)) β€” noted per endpoint.
  • Tokens: access_token (short-lived, ACCESS_TTL_SECONDS) + refresh_token (long-lived, REFRESH_TTL_SECONDS). Refresh via POST /auth/refresh.

Auth β€” /auth

POST /auth/request-otp

Send an OTP to a phone number (creates the user if new).

  • Form: phone (E.164, e.g. +9172048...)
  • 200: { "message": "OTP sent" }
  • 502: SMS provider send failed (invalid key / no wallet balance / KYC incomplete). With OTP_DEBUG=true the 502 detail contains the raw provider error.
  • Note: if FAST2SMS_API_KEY is unset, no SMS is sent β€” the OTP is printed to the server logs ([DEV SMS] to=… otp=…) so login still works in dev.

GET /auth/sms-check πŸ›‘

Diagnose OTP/SMS delivery without a real login. Admin secret via header X-Admin-Secret or ?secret= (browser-friendly).

  • Query: to (optional 10-digit number β€” if given, performs a real test send)
  • 200: { fast2sms_key_present, key_prefix, mode, verdict, provider_response? | provider_error?, hint }
  • verdict: no_provider (key unset) Β· configured_not_tested (no to) Β· ok Β· send_failed

POST /auth/verify-otp

Verify an OTP and receive tokens.

  • Form: phone, otp
  • 200: { access_token, refresh_token, user: {...} }
  • 400: no user / no OTP / expired / invalid
  • Guest: if GUEST_MODE_ENABLED=true and phone == GUEST_PHONE_NUMBER with otp == GUEST_OTP_CODE, returns a guest session (account_type: "guest").

POST /auth/set-pin

Set a login PIN for a phone user.

  • Form: phone, pin (4–6 digits)
  • 200: { "message": "PIN set" }
  • 422: PIN not 4–6 digits

POST /auth/login-pin

Login with phone + PIN.

  • Form: phone, pin
  • 200: { access_token, refresh_token }
  • 401: invalid PIN Β· 400: no user / PIN not set

POST /auth/refresh

Exchange a refresh token for a fresh access token.

  • Form: refresh_token
  • 200: { access_token } Β· 401: invalid/expired

POST /auth/google

Verify a Google ID token and issue app tokens.

  • Form: id_token (Google ID token from the app)
  • 200: { access_token, refresh_token, user: {...} }
  • 503: GOOGLE_WEB_CLIENT_ID not set on the server Β· 401: invalid token
  • Users are keyed internally by google:<sub>.

GET /auth/me πŸ”’

Current user.

  • 200: { id, phone_e164, name, email, avatar_url, created_at, is_active }

PATCH /auth/update-profile πŸ”’

Update profile fields (form-encoded).

  • Form (all optional): name, email, avatar_url
  • 200: updated user object

DELETE /auth/delete-account πŸ”’

Soft-delete (deactivate) the current account.

  • Form: confirm (bool, must be true)
  • 200: { "message": "Account deactivated" }

POST /auth/debug-token (dev only)

Decode a JWT without verifying signature. 404 in production.


Memes β€” /

POST /upload πŸ”’

Upload an image; stores it and returns initial GIF suggestions.

  • Multipart: image (file), mood (optional)
  • 200: { status, uuid, object_key, url, mood, ...suggestions }

POST /suggest πŸ”’

Re-run suggestions for an already-uploaded image.

  • Form: image_object_key, mood (optional)
  • 200: { status, object_key, mood, ...suggestions } Β· 404: key not found

POST /compose πŸ”’

Compose a meme from form fields (single overlay).

  • Form: image_object_key, gif_url | gif_object_key, x, y, width, … (overlay placement)

POST /compose/layout?output_format=gif|png|mp4 πŸ”’

Compose from a full JSON layout (floating images and text over a background). This is what the app's editor uses.

  • JSON body: image_dimensions =
    {
      "bgImage": { "source": "<object_key|url>", "width": 0, "height": 0, "applyCoverBlurAndContainImageFilter": false },
      "floatingImages": [ { "file_url": "...", "width": 200, "relativeX": 0, "relativeY": 0, "rotation": 0, "z": 0 } ],
      "textOverlays":   [ { "text": "LOL", "fontSize": 32, "color": "#FFFFFF", "strokeColor": "#000000",
                            "width": 240, "height": 60, "relativeX": 0, "relativeY": 0, "rotation": 0, "z": 1 } ]
    }
    
  • Query/body: output_format (default gif)
  • 200: { object_key, url, ... }
  • Layering: every overlay (image or text) may carry a z (integer). All overlays are composited in ascending z, so higher z = on top. Omitting z falls back to input order (images first, then text) β€” fully backward compatible.
  • Rotation: rotation (degrees, clockwise) rotates an overlay about its centre; relativeX/Y stay the un-rotated box top-left. Defaults to 0.
  • Text: rendered server-side (Pillow) as bold, stroked meme text; color/strokeColor are hex, width enables word-wrap, width+height define the box the text is centred in.
  • Tip: pass image overlay width only β€” the backend preserves the source aspect ratio (avoids stretched GIFs).

GET /memes?limit&offset πŸ”’

List the current user's generated memes (latest first).

  • 200: { items: [{ id, object_key, content_type, created_at, presigned_url, permanent_url }], count, offset, limit }

GET /memes/presign?object_key=… πŸ”’

Get a 10-minute presigned URL for one owned meme.

GET /memes/{object_key} πŸ”’

Stream the meme bytes through the API (permanent proxy URL, cached 1 year).


Media β€” /media

POST /media/url πŸ”’

Presign any media object (JSON body).

  • Body: object_key, expires_seconds (default 600)
  • 200: { object_key, url, expires_seconds }

POST /media/permanent-url πŸ”’

Get the permanent proxy URL for an owned media object.

  • Body: object_key
  • 200: { object_key, permanent_url, type: "proxy", expires: "never" }

Profile β€” /profile

GET /profile πŸ”’

Current user's profile (from Postgres).

PUT /profile πŸ”’

Update name/email/avatar (JSON body).

  • Body (optional): name, email, avatar_url
  • 200: { "message": "Profile updated" }

Subscriptions β€” /subscriptions

Requires RAZORPAY_KEY_ID + RAZORPAY_KEY_SECRET on the server. Plans (paise/INR): weekly 5000 / 7d, monthly 14000 / 30d, yearly 80000 / 365d.

POST /subscriptions/order πŸ”’

Create a Razorpay order.

  • Form: plan (weekly|monthly|yearly)
  • 200: { order_id, amount, currency, key_id, plan }
  • 400: unknown plan Β· 503: payments not configured / keys rejected (auth) Β· 502: order creation failed
  • With PAYMENTS_DEBUG=true, the 502 detail contains the raw Razorpay error (for debugging only).

POST /subscriptions/verify πŸ”’

Verify the payment signature, activate the plan, and record a payments row (best-effort).

  • Form: razorpay_order_id, razorpay_payment_id, razorpay_signature, plan
  • 200: { status: "active", plan, expires_at }
  • 400: verification failed

GET /subscriptions/status πŸ”’

Current subscription (auto-expires past the end date).

  • 200: { plan, status, active, expires_at, is_premium, usage: { daily_meme_limit, daily_memes_used, daily_memes_remaining, premium_only_formats } }

GET /subscriptions/receipt πŸ”’

Most recent payment, shaped for the receipt UI.

  • 200: { id, plan, plan_label, amount, amount_display, currency, status, method, payment_id, order_id, paid_at, expires_at }
  • 404: no payment on record (client falls back to plan-derived data)

GET /subscriptions/payments πŸ”’

Full payment/transaction history, newest first.

  • 200: { payments: [ <receipt object>, … ] } (empty list if none / table absent)

GET /subscriptions/receipt/{payment_id}.pdf πŸ”’

Download a specific payment's receipt as a PDF (generated with Pillow). Scoped to the owner.

  • 200: application/pdf (Content-Disposition attachment)
  • 404: receipt not found / not owned

GET /subscriptions/config-check πŸ›‘

Diagnose Razorpay config without a checkout. Header X-Admin-Secret.

  • 200: { key_id_present, key_secret_present, key_mode, key_id_prefix, secret_length, had_whitespace_or_quotes, razorpay_lib_installed, verdict, probe_order_id?, probe_error?, hint }
  • ?probe=false skips the live β‚Ή1 test order.

Admin β€” /admin πŸ›‘ (404 in production)

Method Path Purpose
POST /admin/seed-demo-user Create a demo user (phone, pin, otp, issue_tokens)
POST /admin/minio-diagnose Check object-storage config
POST /admin/test-sms Test the SMS provider
GET /admin/users?limit&offset&search List users
GET /admin/users/{id} Get one user
PUT /admin/users/{id} Update name/email/is_active
DELETE /admin/users/{id} Soft-delete (deactivate)
GET /admin/cleanup-guest-data Purge expired guest data

Health & docs

Method Path Purpose
GET /health/deps Dependency/health check
GET /docs RapiDoc UI
GET /redoc ReDoc UI