This example assumes NextJS framework. Adapt to your framework accordingly
Overview
Step 1: Configuring your ARES API route
Copy and paste the following file into your app/api/ARES/route.ts file.
This route will have a GET method and a POST method.
This route deals with the access token, which should never be revealed in the client.
Keep everything in this route on the server side only.
app/api/ARES/route.ts
import { auth, clerkClient } from "@clerk/nextjs/server";
import { NextResponse } from "next/server";
export const runtime = "edge";
// GET Method: Access user's information on ARES's server.
export async function GET() {
const { userId } = await auth();
if (!userId) {
return NextResponse.json({ message: "User not signed in" });
}
// Get the OAuth access token for the user. Necessary to access ARES's API endpoints.
const provider = "custom_ares";
const client = await clerkClient();
const clerkResponse = await client.users.getUserOauthAccessToken(
userId,
provider
);
const accessToken = clerkResponse.data[0]?.token || "";
// Error Handling
if (!accessToken) {
return NextResponse.json(
{ message: "Access token not found" },
{ status: 401 }
);
}
// Get user's info from ARES API Endpoint. More information about this endpoint in the API Endpoints section.
const ARESUrl = "https://oauth.joinares.com/v1/user";
const ARESResponse = await fetch(ARESUrl, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
// Error handling
if (!ARESResponse.ok) {
console.log(ARESResponse);
return NextResponse.json(
{ error: `ARES API error: ${ARESResponse.status}` },
{ status: ARESResponse.status }
);
}
// Handle the response from the ARES API
const ARESUserData = await ARESResponse.json();
return NextResponse.json(ARESUserData);
}
export async function POST(req: Request) {
const { userId } = await auth();
if (!userId) {
return NextResponse.json({ message: "User not found" }, { status: 401 });
}
// Get request body
const { client_id, usage, credits } = await req.json();
// Validate required fields
if (!client_id || !usage || credits === undefined) {
return NextResponse.json(
{ message: "Missing required fields" },
{ status: 400 }
);
}
// Get the OAuth access token for the user. Necessary to access ARES's API endpoints.
const provider = "custom_ares";
const client = await clerkClient();
const clerkResponse = await client.users.getUserOauthAccessToken(
userId,
provider
);
const accessToken = clerkResponse.data[0]?.token || "";
if (!accessToken) {
return NextResponse.json(
{ message: "Access token not found" },
{ status: 401 }
);
}
const UsageUrl = "https://oauth.joinares.com/v1/partner/usage";
const ARESResponse = await fetch(UsageUrl, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
client_id,
usage,
credits,
}),
});
if (!ARESResponse.ok) {
return NextResponse.json(
{ error: `ARES API error: ${ARESResponse.status}` },
{ status: ARESResponse.status }
);
}
const ARESData = await ARESResponse.json();
return NextResponse.json(ARESData);
}
GET Method (Access User Information)
Calling GET Method
With a user signed in with ARES, you can call the API endpoint you just configured to access the user's data from ARES's server.
You can access your /api/ARES however you like, here's an example of calling it from a NextJS server component.
let aresData = null
// ! With Clerk, sometimes the API route won't be able to access the user ID, so it's safer to add the Clerk auth token in lines 7-9, like so:
const response = await fetch(
`${process.env.NEXT_PUBLIC_BASE_URL}/api/ARES`,
{
method: "GET",
headers: {
Authorization: "Bearer " + (await (await auth()).getToken()),
},
}
);
// Access the user data through this variable
aresData = await response.json();
GET Response
A GET request to your /api/ARES endpoint should return the user's information in json format, including the number of credits the user has left.
Step 2: Track user's usage in your app using the API
POST Method (Logs and Tracks User's Usage to Earn Credits)
IMPORTANT: 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 signed in with ARES in order for them to be able to pay-per-use with their ARES credits without having a subscription to your service.
Calling POST Method
Make sure to call this method and check the response success message BEFORE you let your user use the service. This method 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.
Only call the API for users who signed in with ARES, otherwise the API will return an error.
Here's an example of a React button that earns 1 ARES credit for your app (and deducts the credit from the user's account).
"use client";
import React from "react";
const handleAresUsageUpdate = async () => {
try {
// Make sure to configure this API route first (at the beginning of this page).
const response = await fetch("/api/ARES", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
client_id: "1234", // Replace with your actual ARES client ID
usage: "test-button", // Replace with actual usage reason. Must be consistent across usages. (e.g. every time the user uses the test button, use value "test-button", every time the user uses a different button, use value "different-button".
credits: 1, // Replace with actual credits value
}),
});
if (!response.ok) {
throw new Error("Failed to update ARES usage");
}
const data = await response.json();
} catch (error) {
}
};
const UsageButton = () => {
return (
<button
onClick={handleAresUsageUpdate}
>
Update Usage
</button>
);
};
export default UsageButton;
POST Response
Example response stored in the "data" constant from the example button. Once you receive the success message, allow the user to use your service.