curl --request POST \
--url https://api.gigstack.io/v2/invoices/download/fiel \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form cert=@example-file \
--form key=@example-file \
--form 'password=<string>' \
--form sync_start_date=2023-01-01 \
--form 'phone=+5215512345678'const form = new FormData();
form.append('cert', '<string>');
form.append('key', '<string>');
form.append('password', '<string>');
form.append('sync_start_date', '2023-01-01');
form.append('phone', '+5215512345678');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.gigstack.io/v2/invoices/download/fiel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.gigstack.io/v2/invoices/download/fiel"
files = {
"cert": ("example-file", open("example-file", "rb")),
"key": ("example-file", open("example-file", "rb"))
}
payload = {
"password": "<string>",
"sync_start_date": "2023-01-01",
"phone": "+5215512345678"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text){
"success": true,
"message": "FIEL credentials stored successfully",
"data": {
"rfc": "MEE200101ABC",
"expires_at": 1893456000000,
"expires_at_readable": "2030-01-01T06:00:00.000Z",
"serial_number": "00001000000712345678",
"sync_start_date": null,
"phone": "+525512345678",
"registered": true,
"registered_at": 1767225600000
}
}Upload FIEL credentials
Upload your FIEL (Firma Electrónica Avanzada) credentials to enable SAT bulk downloads.
This is the main setup endpoint. It accepts your .cer and .key files, validates them, and — if sync_start_date and phone are provided — automatically registers your business with the SAT in the same request. No separate /register call needed.
What it does:
- Validates the certificate format, extracts your RFC, and checks it matches your gigstack team RFC
- Verifies the certificate is not expired
- Securely encrypts and stores your credentials
- If
sync_start_date+phoneare provided → registers your business with the SAT immediately and enables sync (registered: truein the response)
Request format: multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
cert | file | Yes | .cer file (DER-encoded certificate from SAT) |
key | file | Yes | .key file (DER-encoded encrypted private key from SAT) |
password | string | Yes | Password for the .key file |
sync_start_date | string | Recommended | Start date for SAT sync (YYYY-MM-DD, up to 71 months back) |
phone | string | Recommended | Contact phone in international format (e.g. +5215512345678) |
Note: The FIEL is different from the CSD (Certificado de Sello Digital). The CSD is used to stamp CFDI invoices. The FIEL is used to authenticate with the SAT for bulk downloads.
curl --request POST \
--url https://api.gigstack.io/v2/invoices/download/fiel \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form cert=@example-file \
--form key=@example-file \
--form 'password=<string>' \
--form sync_start_date=2023-01-01 \
--form 'phone=+5215512345678'const form = new FormData();
form.append('cert', '<string>');
form.append('key', '<string>');
form.append('password', '<string>');
form.append('sync_start_date', '2023-01-01');
form.append('phone', '+5215512345678');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.gigstack.io/v2/invoices/download/fiel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.gigstack.io/v2/invoices/download/fiel"
files = {
"cert": ("example-file", open("example-file", "rb")),
"key": ("example-file", open("example-file", "rb"))
}
payload = {
"password": "<string>",
"sync_start_date": "2023-01-01",
"phone": "+5215512345678"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text){
"success": true,
"message": "FIEL credentials stored successfully",
"data": {
"rfc": "MEE200101ABC",
"expires_at": 1893456000000,
"expires_at_readable": "2030-01-01T06:00:00.000Z",
"serial_number": "00001000000712345678",
"sync_start_date": null,
"phone": "+525512345678",
"registered": true,
"registered_at": 1767225600000
}
}Authorizations
Authentication Method: HTTP Bearer token.
The runtime requires the literal Bearer prefix — a bare token in the
Authorization header is rejected with 401 unauthorized.
Header Format: Authorization: Bearer YOUR_API_KEY
Your API key is a JWT. Live keys operate on live data (livemode: true);
test keys operate on isolated test data (livemode: false).
Get your key at: app.gigstack.pro/settings?tab=api
Errors: credential failures are answered by the authentication layer with a raw
{ "message": … } body, not the standardized envelope — 401 for a missing, malformed or
expired token, 403 for a revoked key or a plan without API access. See the Unauthorized
and AuthForbidden responses.
Query Parameters
gigstack Connect: Target team ID for multi-team access.
Requires gigstack Connect enabled on your team and shared billing account.
Also requires the multipleIssuerAccounts feature on your plan. Requests targeting a
team other than the one your API key belongs to return 403 without it.
Only API keys can use it: an OAuth access token sent with another team's id is rejected with
403 Team mismatch with OAuth token.
Optional — omit it entirely unless you are acting on another team. It deliberately
carries no example value so generated snippets do not emit ?team=undefined; when the
parameter is absent, the team is derived from your API key.
Example: ?team=team_xyz789
Body
.cer file — DER-encoded certificate from SAT
.key file — DER-encoded encrypted private key from SAT
Password for the .key file
Start date for historical SAT sync (YYYY-MM-DD, up to 71 months back)
"2023-01-01"
Contact phone in international format
"+5215512345678"