Having trouble with Nextjs API Integration - encountering error 404

I'm currently facing a major issue and I've hit a dead end. I've been spending days trying to connect my local nextjs 14 app to the CVENT API, but I keep receiving a persistent 404 error. Here's what is displayed in the frontend console:

Here is the link to the CVENT documentation:

[Fast Refresh] rebuilding page.tsx:12 GET http://localhost:3000/api/cvent-api 404 (Not Found) eval @ page.tsx:12 Show 94 more frames page.tsx:29 API error: Error: HTTP error! status: 404 at eval (page.tsx:15:17) eval @ page.tsx:29 Promise.catch (async)
eval @ page.tsx:28 Show 97 more frames

.env.local:

# For server-side
CVENT_CLIENT_ID="hereGOEStheID"
CVENT_CLIENT_SECRET="heGoestheSecretID"
CVENT_SCOPE=event/events:read
NEXT_PUBLIC_API_HOSTNAME="https://api-platform-eur.cvent.com"

Api/cvent-api.ts:

import type { NextApiRequest, NextApiResponse } from 'next';
import fetch from 'node-fetch'

const baseUrl = 'https://api-platform-eur.cvent.com';

async function getAccessToken(): Promise<string> {
  const encodedCredentials = Buffer.from(`${process.env.CVENT_CLIENT_ID}:${process.env.CVENT_CLIENT_SECRET}`).toString('base64');
  const authHeader = `Basic ${encodedCredentials}`;

  // Ensure that client_id is defined or provide a fallback empty string to avoid undefined values
  const clientId = process.env.CVENT_CLIENT_ID || '';

  // Correctly format data for POST request
  const params = new URLSearchParams({
    grant_type: 'client_credentials',
    client_id: clientId,
  });

  const response = await fetch(`${baseUrl}/ea/oauth2/token`, { // Use base URL without appending client_id or scopes in the URL
    method: 'POST',
    headers: {
      Authorization: authHeader,
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: params.toString(),
  });

  if (!response.ok) {
    throw new Error(`Error fetching access token, status: ${response.status}`);
  }

  const data = await response.json();
  return data.access_token;
}

// Handler function for the API route
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  try {
    // Obtain a new access token
    const accessToken = await getAccessToken();
    console.log(`access token is: ${accessToken}`)

    // Make API call to Cvent to get attendees list
    const response = await fetch(`${baseUrl}/ea/attendees`, {
      method: "GET",
      headers: {
        "Content-type": "application/json",
        Authorization: `Bearer ${accessToken}`,
      }
    });

    if (!response.ok) {
      throw new Error(`Error fetching attendees list, status: ${response.status}`);
    }

    const data = await response.json();
    console.log('Data is:', data);
    res.status(200).json(data);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Internal Server Error' });
  }
}

page.tsx:

"use client";
import React, { useState, useEffect } from "react";

const IndexPage = () => {
  const [connectionStatus, setConnectionStatus] = useState<string | null>(null);
  const [data, setData] = useState<any[]>([]); // Adjust the type based on your response structure
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    setIsLoading(true);
    fetch("/api/cvent-api") // Corrected URL
      .then((response) => {
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.json();
      })
      .then((responseData) => {
        setData(responseData);
        console.log("API response:", responseData);
        if (responseData && responseData.length > 0) {
          setConnectionStatus("Connection successful and attendees fetched!");
        } else {
          setConnectionStatus("Connection successful but no attendees found.");
        }
      })
      .catch((error) => {
        console.error("API error:", error);
        setError(error.toString());
        setConnectionStatus(`Failed to fetch: ${error.toString()}`);
      })
      .finally(() => setIsLoading(false));
  }, []);

  return (
    <div>
      <h1>Connection Status</h1>
      {isLoading && <p>Loading...</p>}
      {error && <p>{error}</p>}
      {connectionStatus && <p>{connectionStatus}</p>}
      {data && data.length > 0 && (
        <ul>
          {/* Adjust the rendering logic based on your response data */}
          {data.map((attendee) => (
            <li key={attendee.id}>{attendee.name}</li>
          ))}
        </ul>
      )}
    </div>
  );
};

export default IndexPage

Answer №1

It seems like you're utilizing the app router (you referenced v14 and have a "page.tsx") but the API handler you've exposed is for a pages router API handler.

To expose an API endpoint using the app router, you'll need to adhere to a different convention. In your scenario, consider creating a file at app/api/cvent-api/route.ts. Within this file, create a function named GET that takes in a parameter of type Request.

Check out https://nextjs.org/docs/app/building-your-application/routing/route-handlers for more information.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Node.js built-ins require shims, while global variable names are absent

After updating my project using npm-check-updates, I encountered a strange error that stumped me. Despite following the suggested terminal command to install polyfill-node, the issue persisted with no resolution in sight online. The error displayed on the ...

Generating a d.ts file for images in Typescript using automation techniques

Currently, I am working on a React application that utilizes TypeScript and webpack. I am aware that in TypeScript, when importing an image file, it is necessary to create a d.ts file in the current directory and include the following code: // index.d.ts ...

Creating a Vue Directive in the form of an ES6 class: A step-by-step

Is it possible to make a Vue directive as an ES6 Class? I have been attempting to do so, but it doesn't seem to be working correctly. Here is my code snippet: import { DirectiveOptions } from 'vue'; interface WfmCarriageDirectiveModel { ...

The type definition file for 'node' cannot be located

I've encountered some unusual errors after updating angular, webpack, and typescript. Any suggestions on what might be causing this? When I attempt to run the application with npm start, I'm seeing the following errors: [at-loader] Cannot find ...

Having trouble with [at-loader] while incorporating Typescript and react-bootstrap in webpack?

While working with webpack, I encountered an error message when using a component in react-bootstrap along with typescript. The error displayed is as follows: ERROR in [at-loader] ./node_modules/react-bootstrap/esm/NavbarCollapse.d.ts:4:18 TS2320: ...

Adjust the color of the entire modal

I'm working with a react native modal and encountering an issue where the backgroundColor I apply is only showing at the top of the modal. How can I ensure that the color fills the entire modal view? Any suggestions on how to fix this problem and mak ...

Tips for enforcing a mandatory type with TypeScript

Creating a custom type called InputType with optional properties like this: export type InputType = { configJsonUrl?: string; configJsObject?: DataType; rawData?: { [key: string]: string }; action?: () => void; }; export type DataType = { id ...

Ways to adjust height dynamically to auto in React

I am currently stuck on a problem concerning the adjustment of my listing's height dynamically from 300 to auto. My goal is to create a post-like feature where users can click "read more" to expand and view the full post without collapsing it complete ...

Leveraging Angular 4 with Firebase to extract data from a database snapshot

My dilemma lies in retrieving data from a Firebase DB, as I seem to be facing difficulties. Specifically, the use of the "this" operator within the snapshot function is causing issues (highlighted by this.authState.prenom = snapshot.val().prenom) If I att ...

Arranging information within the Ngb-Accordion

Welcome to the code snippet showcasing how to create an accordion in Angular: <ngb-accordion [closeOthers]="false" activeIds="0"> <ng-container class="card" *ngFor="let post of Posts"> <ngb-panel title="{{post.title}} - ...

Is there a way to customize a chart in Ionic 2 to resemble the image provided?

Hello there, I am currently using import {Chart} from 'chart.js'; to generate my chart; however, I am facing some difficulties. My goal is to create a chart similar to the one displayed below. Warm regards //Generating the doughnut this.dou ...

Setting up Firebase App Check in an Angular projectWould you like to know

I have a question about initializing Firebase app check with Angular. I am currently using AngularFire, but I'm not sure how to initialize Firebase app check before using any services. The documentation provides the following initialization code to b ...

Prevent the execution of useEffect on the client side in Next JS if the data has already been retrieved from the server

Upon loading the server side rendered page, data is fetched on the server and passed to client side components. To handle this process, a hook has been created with a state that updates based on checkBox changes. When the state changes, a useEffect is tri ...

Error encountered when attempting to pass i18next instance to I18nextProvider

Issue: Error message: Type 'Promise' is missing certain properties from type 'i18n': t, init, loadResources, use, and more.ts(2740) index.d.ts(344, 3): The expected type is derived from the property 'i18n' declared within ty ...

What is the best way to dynamically add data to a JSON file?

image of JSON file Just a heads up: I'm looking to add data directly without the need to write it to a .json file, perhaps by using Angularfire2 database. user = { name: 'Arthur', age: 21 }; const options = {Headers, responseType: &apo ...

The functionality of the Request interface appears to be malfunctioning

Hey there, I'm currently working on building an API using Express and TypeScript. My goal is to extend the Request object to include a user property. I've done some research on Google and found several posts on StackOverflow that explain how to d ...

What is the reason for the variance in the inferred generic type parameter between an extended interface and a type alias representing an intersection of interfaces?

Why is the generic type parameter inferred differently in the following toy experiment, depending on whether the template is instantiated with an extended type or with an intersected type? This experiment has been simplified from a real-world example. inte ...

Issue with rendering the search component due to a conflict with validate.js

I am currently facing an issue with my search component that includes validation using JavaScript. The problem I am encountering is that when I first focus on the input, the validation and request do not work. However, after losing focus on the input, cli ...

Issues with navigation in React Native Typescript

Currently, I am in the process of developing a new React Native Expo project utilizing TypeScript. I have been attempting to configure navigation following the guidance provided in React Native's TypeScript documentation. However, upon running and sim ...

Executing TypeDoc on a Windows system results in zero files being created and no error messages reported

I have been working on generating documentation for a JavaScript application using TypeDoc. Unfortunately, I am facing an issue where TypeDoc is not outputting any files or errors. To get started, I installed TypeDoc within the project folder: npm instal ...