Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Getting a status code 404 when fetching private files #56

Answered by stevedylandev
Akinbola247 asked this question in Q&A
Discussion options

i'm trying to read private files from pinata, but it doesn't work. Tried using javascript, i got a 404 error. i used curl too, getting the same error :
ERROR

{"error":{"code":404,"status":"Not Found","request":"d47820686d6f8d1003122e6ccc32d928","details":[],"message":"The requested resource could not be found"}}

CURL

curl --request GET \
 --url https://api.pinata.cloud/v3/files/download_link \
 --header "Content-Type: application/json" \
 --header "authorization: Bearer JWT" \
 --data '{"cid":"bafkreia7qm54gyrnk7yzvpkaigtdw4rynzoaxbr43vo4ekrwtlzy7xfkwq"}'

JAVASCRIPT

export async function POST(req: Request) {
 try {
 // Get raw text
 const rawBody = await req.text();
 console.log('Raw body:', rawBody);
 // Clean up unexpected trailing characters like %
 const cleanedBody = rawBody.trim().replace(/%$/, '');
 let parsed;
 try {
 parsed = JSON.parse(cleanedBody);
 } catch (jsonError) {
 throw new Error('Invalid JSON body');
 }
 const { cid } = parsed;
 console.log('Parsed CID:', cid);
 if (!cid) {
 return NextResponse.json(
 { error: 'CID parameter is required' },
 { status: 400 }
 );
 }
 // Ensure JWT is present
 const PINATA_JWT = process.env.PINATA_JWT;
 if (!PINATA_JWT) {
 throw new Error('Missing PINATA_JWT environment variable');
 }
 // Use the correct Pinata endpoint
 const pinataEndpoint = `https://api.pinata.cloud/v3/files/download_link`;
 
 const payload = JSON.stringify({
 url: `https://example.mypinata.cloud/files/${cid}`,
 expires: 3600, // 1 hour expiration
 date: 1724875300,
 method: "GET"
 });
 
 const response = await fetch(pinataEndpoint, {
 method: "POST",
 headers: {
 "Content-Type": "application/json",
 Authorization: `Bearer ${process.env.PINATA_JWT}`
 },
 body: payload
 });
 console.log('Response status:', response);
 
 if (!response.ok) {
 const errorText = await response.text();
 console.error('Pinata API error:', errorText);
 throw new Error(`Pinata API error: ${response.statusText}`);
 }
 const responseData = await response.json();
 if (!responseData.downloadLink) {
 throw new Error('Missing downloadLink in response');
 }
 return NextResponse.json({
 url: responseData.downloadLink,
 expiresAt: responseData.expiresAt || Date.now() + 3600000,
 });
 } catch (error) {
 console.error('Error:', error);
 return NextResponse.json(
 {
 error: 'Failed to generate access link',
 details: error instanceof Error ? error.message : 'Unknown error',
 },
 { status: 500 }
 );
 }
}
You must be logged in to vote

I took a closer look at your original code and hte curl request and I think you might need to tweak a few things to make a valid request. In the body of the of the request you're sending to Pinata you're not passing in your own gateway url, and instead it's the example. We also want to dynamically pass in the date vs hard coding it in. At the very end of the code you're sending something that doesn't exist on the response, it should just be responseData.data per the docs. Can you try using this code instead and make sure you have NEXT_PUBLIC_GATEWAY_URL set with your own gateway in the format of my-example-gateway.mypinata.cloud?

export async function POST(req: Request) {
 try {
 // G...

Replies: 1 comment 9 replies

Comment options

Hey there! Could you give us more info about the file you uploaded? Perhaps use this endpoint and give us the response?

You must be logged in to vote
9 replies
Comment options

Oh! My apologies, I had it set to the public network. Can you try it again with this?

curl --request GET \
 --url 'https://api.pinata.cloud/v3/files/private?cid=bafkreia7qm54gyrnk7yzvpkaigtdw4rynzoaxbr43vo4ekrwtlzy7xfkwq' \
 --header 'Authorization: Bearer <token>'
Comment options

I got this : {"data":{"files":[{"id":"019642ed-71bb-7306-b146-33afce198ea5","name":"private-data-1744879577109.json","cid":"bafkreia7qm54gyrnk7yzvpkaigtdw4rynzoaxbr43vo4ekrwtlzy7xfkwq","size":30,"number_of_files":1,"mime_type":"application/json","group_id":null,"keyvalues":{},"created_at":"2025-04-17T08:46:20.386687Z"}],"next_page_token":"MDE5NjQyZWQtNzFiYi03MzA2LWIxNDYtMzNhZmNlMTk4ZWE1"}}... looks like it's returning the file details.

Comment options

following the endpoint in the curl command, i created an api, however i'm unable to obtain the temporary url to view private files from the response data

export async function POST(req: Request) {
 try {
 const rawBody = await req.text();
 console.log("Raw body:", rawBody);
 const cleanedBody = rawBody.trim().replace(/%$/, "");
 let parsed;
 try {
 parsed = JSON.parse(cleanedBody);
 } catch (jsonError) {
 throw new Error("Invalid JSON body");
 }
 const { cid } = parsed;
 console.log("Parsed CID:", cid);
 if (!cid) {
 return NextResponse.json(
 { error: "CID parameter is required" },
 { status: 400 },
 );
 }
 
 const PINATA_JWT = process.env.PINATA_JWT;
 if (!PINATA_JWT) {
 throw new Error("Missing PINATA_JWT environment variable");
 }
 
 const pinataEndpoint = `https://api.pinata.cloud/v3/files/private?cid=${cid}`;
 const response = await fetch(pinataEndpoint, {
 method: "GET",
 headers: {
 "Content-Type": "application/json",
 Authorization: `Bearer ${PINATA_JWT}`,
 },
 });
 console.log("Response status:", response.status);
 if (!response.ok) {
 const errorText = await response.text();
 console.error("Pinata API error:", errorText);
 throw new Error(`Pinata API error: ${response.statusText}`);
 }
 const responseData = await response.json();
 console.log("all Response data:", response);
 
 return NextResponse.json({
 files: responseData.data.files,
 nextPageToken: responseData.data.next_page_token,
 });
 } catch (error) {
 console.error("Error:", error);
 return NextResponse.json(
 {
 error: "Failed to fetch private file information",
 details: error instanceof Error ? error.message : "Unknown error",
 },
 { status: 500 },
 );
 }
}
Comment options

I took a closer look at your original code and hte curl request and I think you might need to tweak a few things to make a valid request. In the body of the of the request you're sending to Pinata you're not passing in your own gateway url, and instead it's the example. We also want to dynamically pass in the date vs hard coding it in. At the very end of the code you're sending something that doesn't exist on the response, it should just be responseData.data per the docs. Can you try using this code instead and make sure you have NEXT_PUBLIC_GATEWAY_URL set with your own gateway in the format of my-example-gateway.mypinata.cloud?

export async function POST(req: Request) {
 try {
 // Get raw text
 const rawBody = await req.text();
 console.log('Raw body:', rawBody);
 // Clean up unexpected trailing characters like %
 const cleanedBody = rawBody.trim().replace(/%$/, '');
 let parsed;
 try {
 parsed = JSON.parse(cleanedBody);
 } catch (jsonError) {
 throw new Error('Invalid JSON body');
 }
 const { cid } = parsed;
 console.log('Parsed CID:', cid);
 if (!cid) {
 return NextResponse.json(
 { error: 'CID parameter is required' },
 { status: 400 }
 );
 }
 // Ensure JWT is present
 const PINATA_JWT = process.env.PINATA_JWT;
 if (!PINATA_JWT) {
 throw new Error('Missing PINATA_JWT environment variable');
 }
 // Use the correct Pinata endpoint
 const pinataEndpoint = `https://api.pinata.cloud/v3/files/download_link`;
 
 const date = Math.floor(new Date().getTime() / 1000);
 const payload = JSON.stringify({
 url: `${process.env.NEXT_PUBLIC_GATEWAY_URL}/files/${cid}`,
 expires: 3600, // 1 hour expiration
 date
 method: "GET"
 });
 
 const response = await fetch(pinataEndpoint, {
 method: "POST",
 headers: {
 "Content-Type": "application/json",
 Authorization: `Bearer ${process.env.PINATA_JWT}`
 },
 body: payload
 });
 console.log('Response status:', response);
 
 if (!response.ok) {
 const errorText = await response.text();
 console.error('Pinata API error:', errorText);
 throw new Error(`Pinata API error: ${response.statusText}`);
 }
 const responseData = await response.json();
 return NextResponse.json({
 url: responseData.data
 });
 } catch (error) {
 console.error('Error:', error);
 return NextResponse.json(
 {
 error: 'Failed to generate access link',
 details: error instanceof Error ? error.message : 'Unknown error',
 },
 { status: 500 }
 );
 }
}

Also I would highly recommend using our SDK as it would be a lot easier than using the API directly: https://docs.pinata.cloud/sdk/gateways/private/create-signed-url

It's possible there's still an issue with the file itself so please give this a try and let me know if you get an error message!

Answer selected by Akinbola247
Comment options

The SDK worked for me. Thanks!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /