Getting a status code 404 when fetching private files #56
-
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 } ); } }
Beta Was this translation helpful? Give feedback.
All reactions
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
-
Hey there! Could you give us more info about the file you uploaded? Perhaps use this endpoint and give us the response?
Beta Was this translation helpful? Give feedback.
All reactions
-
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>'
Beta Was this translation helpful? Give feedback.
All reactions
-
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.
Beta Was this translation helpful? Give feedback.
All reactions
-
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 }, ); } }
Beta Was this translation helpful? Give feedback.
All reactions
-
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!
Beta Was this translation helpful? Give feedback.
All reactions
-
The SDK worked for me. Thanks!!
Beta Was this translation helpful? Give feedback.
All reactions
-
🎉 1 -
❤️ 1