cred.diy/ docs
    Sign inGet an API key
    All documentation

    Signup Attribution - cred.diy API documentation

    Signup Attribution

    Track which app, landing page, or marketing channel each end user came from — and target promotions per app. Every end user carries three optional attribution fields.

    The three fields

    • signup_url — full URL the user signed up from (e.g. https://app1.example.com/signup?ref=twitter).
    • signup_host — normalized lowercase hostname. Auto-derived by cred from signup_url if omitted; you can override by sending it explicitly.
    • signup_credit_type_id — the credit type the user signed up for (useful for cross-app / multi-product attribution).

    Sending the app origin

    You have three ways to tell cred which app a call came from, checked in this order:

    1. signup_url (or signup_host) in the request body — best for server-to-server calls where you know the exact signup page.
    2. An x-app-origin: https://yourapp.com request header — set this once in your HTTP client. The official SDK sends it automatically when you pass appOrigin to the client.
    3. The browser's Origin / Referer header — used automatically for calls made from a browser.

    Optional (but strongly recommended) on POST /users, POST /users/bulk, /issue and /deduct — these calls always succeed without it, they just leave attribution blank.

    First-touch semantics

    Once set on an end user, these fields are never overwritten by later calls. Safe to send on every request — cred latches the first non-null value. Cred has no way to know which of your apps a user came from, so your app must send signup_url and signup_credit_type_id. Blank attribution is backfilled, not frozen: because cred latches the first non-null value, a user created without attribution is filled in by their next call that carries an app origin. Only users who never call again stay blank — backfill those from the dashboard.

    Endpoints that accept attribution

    Send the three fields as top-level body parameters on:

    • POST /users and POST /users/bulk
    • POST /issue and POST /deduct (stamps the user on first-touch if they don't exist yet)
    • POST /hosted-checkout (also stored on the resulting purchase)
    • Presale checkout
    // Create a user with signup attribution
    // signup_host is auto-derived from signup_url — no need to send it
    const response = await fetch(
      'https://eutdgemlrpvnxfkkpvlu.supabase.co/functions/v1/credits-api/users',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': 'sk_live_your_api_key'
        },
        body: JSON.stringify({
          external_id: 'user_123',
          email: 'user@example.com',
          signup_url: 'https://app1.example.com/signup?ref=twitter',
          signup_credit_type_id: 'ct_abc123'
        })
      }
    );

    Filter users by attribution

    GET /users accepts two additional filter query params: signup_host and signup_credit_type_id.

    // Filter users by attribution
    // signup_host  — normalized hostname (e.g. app1.example.com)
    // signup_credit_type_id — the credit type the user signed up for
    const res = await fetch(
      'https://eutdgemlrpvnxfkkpvlu.supabase.co/functions/v1/credits-api/users?signup_host=app1.example.com&limit=100',
      { headers: { 'x-api-key': 'sk_live_your_api_key' } }
    );

    GET /signup-analytics

    User counts, purchase counts, and revenue grouped by signup_host. Pass days=0 for all-time (default: 30).

    // GET /signup-analytics?days=30
    // User counts, purchase counts, and revenue grouped by signup_host.
    // Pass days=0 for all-time (default: 30).
    const res = await fetch(
      'https://eutdgemlrpvnxfkkpvlu.supabase.co/functions/v1/credits-api/signup-analytics?days=30',
      { headers: { 'x-api-key': 'sk_live_your_api_key' } }
    );
    
    // {
    //   "breakdown": [
    //     {
    //       "signup_host": "app1.example.com",
    //       "signup_credit_type_id": "ct_abc",
    //       "signup_credit_type_name": "GEMS",
    //       "user_count": 1250,
    //       "purchase_count": 87,
    //       "revenue": 4321.50
    //     }
    //   ]
    // }

    Your first credit is one request away.

    Create a project, copy an API key, and issue a credit from your server.