Get Public Profile by Code

Retrieve a user's public CANSKAN profile using their QR code hash.

GET /profile/{code}

Retrieve a public CANSKAN profile using the user's QR code identifier.


Base URL

https://api.canskan.com

Endpoint

GET /profile/{code}

Path Parameters

  • coderequired, string 32-character lowercase MD5 hash associated with the user's email.

    Example:

    e4d909c290d0fb1ca068ffaddf22cbd0
    

Request

HTTP Request

GET https://api.canskan.com/profile/e4d909c290d0fb1ca068ffaddf22cbd0
Accept: application/json

Query Parameters (optional / reserved)

  • fields – Comma-separated fields from public_profile to include.
  • expand – Reserved for future extended data.

Response

Successful Response (200)

{
  "status": "success",
  "data": {
    "code": "e4d909c290d0fb1ca068ffaddf22cbd0",
    "type": "public_profile",
    "public_profile": {
      "display_name": "Harley Doyon",
      "headline": "Full-stack engineer & QR identity enthusiast",
      "avatar_url": "https://cdn.canskan.com/avatars/e4d909c2.png",
      "bio": "I use my CANSKAN QR code to simplify forms & check-ins everywhere.",
      "links": {
        "website": "https://harley.dev",
        "twitter": "https://twitter.com/harley",
        "linkedin": "https://linkedin.com/in/harleydoyon"
      },
      "meta": {
        "locale": "en-PH",
        "timezone": "Asia/Manila"
      }
    },
    "flags": {
      "is_active": true,
      "is_deletable": true,
      "is_public": true
    },
    "created_at": "2025-11-20T09:30:00.000Z",
    "updated_at": "2025-11-20T10:15:00.000Z"
  }
}

Error Responses

All error responses share this structure:

{
  "status": "error",
  "error": {
    "code": "string",
    "message": "Human-readable error message.",
    "details": {
      "field": "optional extra info"
    }
  }
}

400 – Invalid Code Format

{
  "status": "error",
  "error": {
    "code": "invalid_code_format",
    "message": "The supplied profile code is not valid.",
    "details": {
      "expected": "32-character lowercase hex MD5 string"
    }
  }
}

404 – Profile Not Found

{
  "status": "error",
  "error": {
    "code": "profile_not_found",
    "message": "No public profile was found for the given code."
  }
}

410 – Profile Deleted

{
  "status": "error",
  "error": {
    "code": "profile_gone",
    "message": "This profile has been deleted and is no longer available."
  }
}

429 – Rate Limit Exceeded

{
  "status": "error",
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please wait before trying again."
  }
}

500 – Server Error

{
  "status": "error",
  "error": {
    "code": "internal_server_error",
    "message": "An unexpected error occurred. Please try again later."
  }
}

Rate Limiting

Public access to GET /profile/{code} is rate-limited.

  • Limit: 60 requests per minute per IP
  • The API returns the following headers with each response:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1732099200
  • X-RateLimit-Reset is a Unix timestamp indicating when the limit resets.

If the limit is exceeded, the API returns HTTP 429 and stops serving requests until the window resets.


Usage Examples

curl

curl "https://api.canskan.com/profile/e4d909c290d0fb1ca068ffaddf22cbd0" \
  -H "Accept: application/json"

JavaScript (fetch)

const code = "e4d909c290d0fb1ca068ffaddf22cbd0"

fetch(`https://api.canskan.com/profile/${code}`, {
  headers: {
    Accept: "application/json"
  }
})
  .then(async (res) => {
    if (!res.ok) {
      const error = await res.json()
      throw error
    }
    return res.json()
  })
  .then((payload) => {
    console.log("Profile:", payload.data.public_profile)
  })
  .catch(console.error)

Python (requests)

import requests

code = "e4d909c290d0fb1ca068ffaddf22cbd0"
url = f"https://api.canskan.com/profile/{code}"

response = requests.get(url, headers={"Accept": "application/json"})

if response.ok:
    data = response.json()
    print("Profile:", data["data"]["public_profile"])
else:
    error = response.json()
    print("Error:", error["error"]["message"])

Versioning

By default, the API uses the latest stable version.

You can optionally send:

X-Api-Version: 1

to pin the version. If omitted, the latest stable version is used.


Additional Notes

  • The code parameter is case-sensitive and must be lowercase.
  • Only public profile information is returned. Users control what information is public through their account settings.
  • The API supports CORS for client-side requests from any origin.
  • Future versions may include pagination for extended data (e.g., activity feeds).