ARES for Partners
  • ARES OAuth Integration Guide
  • Reference
    • Configuring OAuth
      • Auth0 by Okta
      • Clerk
      • Supabase
      • Manual Integration
    • Configuring App to Earn Credits
      • Track Usage with Clerk
      • Track Usage with Auth0
      • Track Usage with Supabase
  • API Endpoints
Powered by GitBook
On this page
  • Step 1: Configure .env File
  • Step 2: Configure generateSignature Function
  • Step 3: Create a Function to Access User's Information on ARES
  • Step 4: Create a Function to Track User's Usage
  1. Reference
  2. Configuring App to Earn Credits

Track Usage with Supabase

Here's the architecture on tracking ARES usage with Supabase:

Partner Backend->>ARES API: Send HMAC-signed request (email + client_id + timestamp)
ARES API-->>Partner Backend: Allow/deny access + remaining credits
Partner Backend-->>Partner Frontend: Proceed/block action

Step 1: Configure .env File

Set your ARES environment variables

ARES_CLIENT_ID=your_client_id
ARES_CLIENT_SECRET=your_client_secret

# ... existing environment variables ... 

Step 2: Configure generateSignature Function

Create this function in your app (preferrably in a dedicated route for everything about ARES):

This should only be in the server side of your application

app/api/ares/route.ts
export function generateSignature(
  clientSecret: string,
  email: string,
  timestamp: string
) {
  const payload = `${email}|${timestamp}`;
  return crypto
    .createHmac("sha256", clientSecret)
    .update(payload)
    .digest("hex");
}

You will need to use a HMAC signature to access ARES's APIs.

Step 3: Create a Function to Access User's Information on ARES

This function requires the generateSignature function from Step 2, so make sure to have it in the same file or import the function.

This function should only run on the server side of your application.

This function is used to check whether the user signed in to your Supabase app have an ARES account by using their email. If they don't, it will return an error. Since Supabase doesn't support custom OAuth providers yet, this method is a temporary workaround.

app/api/ares/route.ts
// This example is using the NextJS Framework

// ... generateSignature function ...

import { NextRequest, NextResponse } from "next/server";

export async function GET(request: NextRequest) {
  const userEmail = // Retrieve the signed in user's email. This part is intentionally left blank in the example. Please implement your own solution.
  
  const timestamp = Date.now().toString();
  const clientId = process.env.ARES_CLIENT_ID;
  const clientSecret = process.env.ARES_CLIENT_SECRET;

  if (!clientId || !clientSecret) {
    return NextResponse.json(
      { error: "Missing API configuration" },
      { status: 500 }
    );
  }

  const signature = generateSignature(
    clientSecret,
    userEmail,
    timestamp
  );

  try {
    const response = await fetch(
      "https://oauth.joinares.com/v1/partner/user-info",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          client_id: clientId,
          email: userEmail,
          timestamp,
          signature,
        }),
      }
    );

    const data = await response.json();
    return NextResponse.json(data, { status: response.status });
  } catch (error) {
    return NextResponse.json(
      { error: "Failed to fetch user info" },
      { status: 500 }
    );
  }
}

Example Response from calling the GET method defined above:

{
  "user": {
    "id": "f7ef2f90-9d1a-4afc-a510-f94ab0694b15",
    "email": "ceo@example.com",
    "name": Andraz,
    "credits": 1400,
    "picture": null
  }
}

Step 4: Create a Function to Track User's Usage

This will earn credits for your app and deduct the credits from the user's account.

This function should be kept only on the server side of your application

app/api/ares/route.ts
// ... code from step 2 & 3 ... 

export async function POST(request: NextRequest) {
  const userEmail = // Retrieve the signed in user's email. This part is intentionally left blank in the example. Please implement your own solution.

  const { usage, credits } = await request.json();
  const timestamp = Date.now().toString();
  const clientId = process.env.ARES_CLIENT_ID;
  const clientSecret = process.env.ARES_CLIENT_SECRET;

  if (!usage || !credits || !clientId || !clientSecret) {
    return NextResponse.json(
      { error: "Missing required parameters" },
      { status: 400 }
    );
  }

  const signature = generateSignature(clientSecret, userEmail, timestamp);

  try {
    const response = await fetch(
      "https://oauth.joinares.com/v1/partner/validate-usage",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          client_id: clientId,
          email: userEmail,
          timestamp,
          signature,
          usage,
          credits,
        }),
      }
    );

    const data = await response.json();
    return NextResponse.json(data, { status: response.status });
  } catch (error) {
    return NextResponse.json(
      { error: "Failed to validate usage" },
      { status: 500 }
    );
  }
}

Example Response from the POST method of the route:

{
  message: 'Success',
  usage: {
    usage_timestamp: '2025-02-26T01:59:35.113831+00:00',
    user_id: 'f7ef2f90-9d1a-4afc-a510-f945e75d4b15',
    client_id: 'supabase_client',
    credits_earned: 1,
    usage: 'supabase-button'
  }
},
{ 
  status: 200 
}

Make sure to call this method and check the response success message BEFORE you let your user use the service. This message logs the usage on ARES's server, keeping track of the ARES credits you've earned. Once you have called this method and receive a success message, allow the user to continue.

If you check whether or not a user has a subscription before allowing them to use a certain feature on your app, make sure to disable that for users with ARES in order for them to be able to pay-per-use with their ARES credits without having a subscription to your service.

Example: Button that costs 1 credit to click

// Example POST request to the route above.

 async function useCredit() {
    "use server";

    const response = await fetch(`${process.env.NEXT_PUBLIC_URL}/api/ares`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        usage: "supabase-button",
        credits: 1,
      }),
    });
    return response.json();
  }


// Example Component
   <form action={useCredit}>
        <button type="submit">
            Use 1 Credit
        </button>
    </form>

PreviousTrack Usage with Auth0NextAPI Endpoints

Last updated 3 months ago