Quickstart

From zero to integrated in 60 seconds.

Quilix data is public by design. Anyone can read a published portfolio with no account, no key, no setup. If you want to write data programmatically, you'll need an account and a Personal Access Token — both flows are covered below.

All docs / Quickstart

1. Read a published portfolio (no auth)

The headless read API returns the same data we render at /<username>/ as JSON. CORS is open, so you can call it directly from any browser.

curl

curl https://quilix.yahyacodes.site/api/v1/public/yahya/portfolio/

JavaScript (fetch)

const res = await fetch(
  "https://quilix.yahyacodes.site/api/v1/public/yahya/portfolio/",
);
const portfolio = await res.json();
console.log(portfolio.owner.full_name);
console.log(portfolio.projects.length);

Python (requests)

import requests

r = requests.get("https://quilix.yahyacodes.site/api/v1/public/yahya/portfolio/")
r.raise_for_status()
data = r.json()
print(data["owner"]["full_name"])

Response shape

{
  "owner": { "username": "yahya", "full_name": "...", "avatar": null },
  "portfolio": {
    "headline": "Senior Backend Engineer",
    "tagline": "Django + DRF",
    "bio": "...",
    "is_published": true,
    "view_count": 0
  },
  "social_links": [...],
  "education": [...],
  "experience": [...],
  "projects": [...],
  "skills": [...],
  "certifications": [...]
}

Returns 404 if the user doesn't exist, the portfolio is unpublished, or the owner's subscription has lapsed. See Errors.

2. Write data via the dashboard API (JWT)

Login (or sign up) gets you a short-lived access token + a longer-lived refresh token. Send the access token as a Bearer header on protected endpoints.

Sign up

curl -X POST https://quilix.yahyacodes.site/api/v1/auth/register/email/ \
  -H "Content-Type: application/json" \
  -d '{
    "email": "you@example.com",
    "password": "very-long-password",
    "full_name": "Your Name",
    "username": "yourname"
  }'

Log in

curl -X POST https://quilix.yahyacodes.site/api/v1/auth/login/email/ \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"very-long-password"}'

# → { "tokens": { "access": "...", "refresh": "..." }, "user": { ... } }

Update your portfolio

curl -X PATCH https://quilix.yahyacodes.site/api/v1/portfolio/ \
  -H "Authorization: Bearer <access-token>" \
  -H "Content-Type: application/json" \
  -d '{"headline":"Senior Backend Engineer","tagline":"Django + DRF"}'

Refresh an expired access token

curl -X POST https://quilix.yahyacodes.site/api/v1/auth/refresh/ \
  -H "Content-Type: application/json" \
  -d '{"refresh":"<refresh-token>"}'

Access tokens last 15 minutes; refresh tokens last 14 days and rotate on use. See Authentication for the full picture.

3. Programmatic writes with a Personal Access Token

For CI, syncing from a CMS, or scripts you don't want to re-authenticate every 14 days, generate a long-lived Personal Access Token in the dashboard at /app/account/access-tokens. It looks like phub_pat_… and authenticates the same way as a JWT access token.

# Issue
curl -X POST https://quilix.yahyacodes.site/api/v1/me/access-tokens/ \
  -H "Authorization: Bearer <jwt-access>" \
  -H "Content-Type: application/json" \
  -d '{"name":"ci-content-sync"}'

# → { "token": "phub_pat_xxxx...", "name": "ci-content-sync", "prefix": "phub_pat_xxxx", "id": "..." }
# IMPORTANT: the plaintext token is shown ONCE. Store it in a secret manager.

# Use
curl -X POST https://quilix.yahyacodes.site/api/v1/portfolio/projects/ \
  -H "Authorization: Bearer phub_pat_xxxx..." \
  -H "Content-Type: application/json" \
  -d '{"title":"My CI-built project","summary":"Synced from a CMS"}'

PATs never expire by default; revoke them from the dashboard the moment one leaks. Server logs include only the prefix, never the plaintext.

Next steps