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.io/api/v1/public/yahya/portfolio/

JavaScript (fetch)

const res = await fetch(
  "https://quilix.io/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.io/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 or the portfolio is unpublished. 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.io/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.io/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.io/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.io/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.io/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.io/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