Overview
The /api/get-context-upload endpoint allows you to fetch competition context using your own Kaggle API credentials. This is required for:
Private competitions
Competitions with restricted data access
Rate limit avoidance (uses your personal Kaggle quota)
Endpoint: POST /api/get-context-upload
Content-Type: multipart/form-data
Authentication: Not required (credentials provided in request)
Your kaggle.json file contains sensitive API credentials. Never commit it to version control or share it publicly.
Request
This endpoint uses multipart/form-data to accept file uploads.
Full Kaggle competition URL
Number of top notebooks to include (1-10)
Your kaggle.json credentials file containing username and key
Getting your kaggle.json
Access your account settings
Click your profile picture → Settings
Create new API token
Scroll to API section → Click Create New Token
Download kaggle.json
Your browser will download kaggle.json automatically
The file format:
{
"username" : "your-kaggle-username" ,
"key" : "your-api-key-here"
}
Response
Returns a CompetitionResponse with processing status, as the ingestion happens in the background.
Competition slug extracted from the URL
Always “Processing…” during initial request
Always processing (background task started)
Confirmation message: “Private ingestion started with provided credentials.”
Examples
cURL
curl -X POST http://localhost:8000/api/get-context-upload \
-F "url=https://www.kaggle.com/competitions/private-competition" \
-F "top_n=5" \
-F "token_file=@/path/to/kaggle.json"
Python
import requests
with open ( 'kaggle.json' , 'rb' ) as f:
files = { 'token_file' : f}
data = {
'url' : 'https://www.kaggle.com/competitions/my-private-comp' ,
'top_n' : 3
}
response = requests.post(
'http://localhost:8000/api/get-context-upload' ,
files = files,
data = data
)
result = response.json()
print ( f "Status: { result[ 'status' ] } " )
print ( f "Message: { result[ 'message' ] } " )
print ( f "Slug: { result[ 'slug' ] } " )
JavaScript (Browser)
const formData = new FormData ();
formData . append ( 'url' , 'https://www.kaggle.com/competitions/private-comp' );
formData . append ( 'top_n' , '5' );
formData . append ( 'token_file' , fileInput . files [ 0 ]); // from <input type="file">
const response = await fetch ( 'http://localhost:8000/api/get-context-upload' , {
method: 'POST' ,
body: formData
});
const data = await response . json ();
console . log ( data . message ); // "Private ingestion started with provided credentials."
Background processing
Unlike the public endpoints, this always triggers background processing:
Submit credentials
POST your URL and kaggle.json file
Receive processing status
Get immediate response with processing status
Wait 30-60 seconds
Background job fetches competition data using your credentials
Check status
Use GET /api/competitions/{slug} to check if processing completed
Retrieve results
Once status is completed, the toon_content field contains your data
Credential validation
The endpoint validates your kaggle.json before accepting the request:
# From backend/services/validation_service.py
async def validate_and_read_token_file ( token_file : UploadFile) -> dict :
"""Validates kaggle.json structure"""
content = await token_file.read()
data = json.loads(content)
if "username" not in data or "key" not in data:
raise HTTPException( 400 , "Invalid kaggle.json format" )
return data
Security considerations
Your credentials are never stored. They’re used only for the immediate ingestion task and discarded afterward.
Credentials are validated but not persisted to the database
Used only in the background task context
Recommend rotating your Kaggle API token after use
KaggleIngest does not log credential contents
Error responses
Invalid kaggle.json format or missing required fields {
"detail" : "Invalid kaggle.json format"
}
Missing file or invalid form data {
"detail" : [
{
"loc" : [ "body" , "token_file" ],
"msg" : "field required" ,
"type" : "value_error.missing"
}
]
}
Checking completion status
After submitting, poll the competition endpoint:
import time
import requests
# 1. Submit with credentials
response = requests.post(
'http://localhost:8000/api/get-context-upload' ,
files = { 'token_file' : open ( 'kaggle.json' , 'rb' )},
data = { 'url' : 'https://kaggle.com/c/private-comp' , 'top_n' : 3 }
)
slug = response.json()[ 'slug' ]
# 2. Poll for completion
for attempt in range ( 12 ): # 2 minutes max
time.sleep( 10 )
status_resp = requests.get( f 'http://localhost:8000/api/competitions/ { slug } ' )
data = status_resp.json()
if data[ 'status' ] == 'completed' :
print ( "Success! Context ready:" )
print (data[ 'toon_content' ])
break
elif data[ 'status' ] == 'failed' :
print ( f "Failed: { data.get( 'message' ) } " )
break
else :
print ( f "Attempt { attempt + 1 } : Still processing..." )
Public competitions Use the public endpoint for non-private competitions
Check status Poll for completion status