curl --request POST \
--url https://api.gigstack.io/v2/invoices/income \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"automation_type": "payment",
"currency": "MXN",
"use": "G03",
"payment_form": "03",
"payment_method": "PUE",
"client": {
"id": "client_1234567890"
},
"items": [
{
"description": "Professional consulting services",
"sku": "CONS-001",
"product_key": "80141503",
"unit_key": "ACT",
"unit_name": "Actividad",
"unit_price": 1500,
"taxability": "02",
"taxes": [
{
"type": "IVA",
"rate": 0.16,
"factor": "Tasa",
"withholding": false,
"inclusive": false
}
],
"quantity": 1
}
],
"send_email": true,
"emails": [
"cliente@empresa.com"
],
"metadata": {
"project_id": "PROJ-2024-001",
"department": "consulting"
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
automation_type: 'payment',
currency: 'MXN',
use: 'G03',
payment_form: '03',
payment_method: 'PUE',
client: {id: 'client_1234567890'},
items: [
{
description: 'Professional consulting services',
sku: 'CONS-001',
product_key: '80141503',
unit_key: 'ACT',
unit_name: 'Actividad',
unit_price: 1500,
taxability: '02',
taxes: [
{type: 'IVA', rate: 0.16, factor: 'Tasa', withholding: false, inclusive: false}
],
quantity: 1
}
],
send_email: true,
emails: ['cliente@empresa.com'],
metadata: {project_id: 'PROJ-2024-001', department: 'consulting'}
})
};
fetch('https://api.gigstack.io/v2/invoices/income', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.gigstack.io/v2/invoices/income"
payload = {
"automation_type": "payment",
"currency": "MXN",
"use": "G03",
"payment_form": "03",
"payment_method": "PUE",
"client": { "id": "client_1234567890" },
"items": [
{
"description": "Professional consulting services",
"sku": "CONS-001",
"product_key": "80141503",
"unit_key": "ACT",
"unit_name": "Actividad",
"unit_price": 1500,
"taxability": "02",
"taxes": [
{
"type": "IVA",
"rate": 0.16,
"factor": "Tasa",
"withholding": False,
"inclusive": False
}
],
"quantity": 1
}
],
"send_email": True,
"emails": ["cliente@empresa.com"],
"metadata": {
"project_id": "PROJ-2024-001",
"department": "consulting"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"message": "Invoice created successfully",
"data": {
"uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
"client": {
"id": "client_1234567890",
"name": "Juan Pérez García",
"email": "juan.perez@ejemplo.com",
"tax_id": "PEGJ800101ABC",
"from": "api",
"livemode": true,
"owner": "user_1234567890",
"team": "team_1234567890",
"created_at": 1767225600000
},
"status": "valid",
"currency": "MXN",
"exchange_rate": 1,
"total": 1160,
"subtotal": 1000,
"taxes": 160,
"discount": 0,
"series": "A",
"folio_number": 123,
"invoice_type": "I",
"payment_method": "PUE",
"items": [
{
"id": "item_1234567890",
"description": "Professional consulting services",
"quantity": 1,
"unit_price": 1000,
"product_key": "80141503",
"unit_key": "E48"
}
],
"created_at": 1677651234,
"livemode": true,
"owner": "user_1234567890"
}
}Create income invoice
Integration note: This endpoint stamps immediately. For a reviewable document, create a draft first. Successful issuance returns HTTP 200 and data.uuid. Fiscal validity does not establish that payment has been received. Read shared fields and the Mexico or Colombia guide for country-specific meaning. The linked fiscal recipes and staging issuance results use a Mexican issuer.
Create a new income invoice with CFDI 4.0 compliance.
Safe retries with idempotency_key. Send your own identifier for the invoice (for example your
order id) in idempotency_key. gigstack claims the key before charging a credit or stamping, so
repeating the request cannot issue a second CFDI or charge twice:
- The invoice already exists:
400withmessage.duplicate: trueandmessage.uuid. - Another request with the key is still being processed:
409idempotency_in_progress. Retry later. - The PAC’s answer was lost:
503PAC_OUTCOME_UNKNOWNwithretryable: true. Retry with the same key: the same XML and folio are sent again, so the PAC stamps it once or returns the stamp it already made. - The PAC can’t confirm an earlier attempt:
409STAMP_NEEDS_REVIEW. Don’t retry; contact support. - The SAT or PAC rejected the data:
400, and the key is free again for a corrected request.
Without an idempotency_key none of this applies, and after a 503 PAC_OUTCOME_UNKNOWN
(retryable: false) you can’t tell whether the invoice exists: look it up before sending it again.
To issue many invoices at once, use POST /invoices/income/batch.
gigstack Connect: Create invoices for other teams using the team parameter.
curl --request POST \
--url https://api.gigstack.io/v2/invoices/income \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"automation_type": "payment",
"currency": "MXN",
"use": "G03",
"payment_form": "03",
"payment_method": "PUE",
"client": {
"id": "client_1234567890"
},
"items": [
{
"description": "Professional consulting services",
"sku": "CONS-001",
"product_key": "80141503",
"unit_key": "ACT",
"unit_name": "Actividad",
"unit_price": 1500,
"taxability": "02",
"taxes": [
{
"type": "IVA",
"rate": 0.16,
"factor": "Tasa",
"withholding": false,
"inclusive": false
}
],
"quantity": 1
}
],
"send_email": true,
"emails": [
"cliente@empresa.com"
],
"metadata": {
"project_id": "PROJ-2024-001",
"department": "consulting"
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
automation_type: 'payment',
currency: 'MXN',
use: 'G03',
payment_form: '03',
payment_method: 'PUE',
client: {id: 'client_1234567890'},
items: [
{
description: 'Professional consulting services',
sku: 'CONS-001',
product_key: '80141503',
unit_key: 'ACT',
unit_name: 'Actividad',
unit_price: 1500,
taxability: '02',
taxes: [
{type: 'IVA', rate: 0.16, factor: 'Tasa', withholding: false, inclusive: false}
],
quantity: 1
}
],
send_email: true,
emails: ['cliente@empresa.com'],
metadata: {project_id: 'PROJ-2024-001', department: 'consulting'}
})
};
fetch('https://api.gigstack.io/v2/invoices/income', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.gigstack.io/v2/invoices/income"
payload = {
"automation_type": "payment",
"currency": "MXN",
"use": "G03",
"payment_form": "03",
"payment_method": "PUE",
"client": { "id": "client_1234567890" },
"items": [
{
"description": "Professional consulting services",
"sku": "CONS-001",
"product_key": "80141503",
"unit_key": "ACT",
"unit_name": "Actividad",
"unit_price": 1500,
"taxability": "02",
"taxes": [
{
"type": "IVA",
"rate": 0.16,
"factor": "Tasa",
"withholding": False,
"inclusive": False
}
],
"quantity": 1
}
],
"send_email": True,
"emails": ["cliente@empresa.com"],
"metadata": {
"project_id": "PROJ-2024-001",
"department": "consulting"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"message": "Invoice created successfully",
"data": {
"uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
"client": {
"id": "client_1234567890",
"name": "Juan Pérez García",
"email": "juan.perez@ejemplo.com",
"tax_id": "PEGJ800101ABC",
"from": "api",
"livemode": true,
"owner": "user_1234567890",
"team": "team_1234567890",
"created_at": 1767225600000
},
"status": "valid",
"currency": "MXN",
"exchange_rate": 1,
"total": 1160,
"subtotal": 1000,
"taxes": 160,
"discount": 0,
"series": "A",
"folio_number": 123,
"invoice_type": "I",
"payment_method": "PUE",
"items": [
{
"id": "item_1234567890",
"description": "Professional consulting services",
"quantity": 1,
"unit_price": 1000,
"product_key": "80141503",
"unit_key": "E48"
}
],
"created_at": 1677651234,
"livemode": true,
"owner": "user_1234567890"
}
}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
Unknown top-level keys are rejected (400 validation_failed / unexpected_key) — body
validation runs in strict allowlist mode, so a field the schema does not declare
produces that error. In particular there is no client_id field: reference an
existing client with client: { "id": "client_…" }, or look one up with
client: { "search": { "on_key": "tax_id", "on_value": "…" } }. Supplying both id
and search on the same object is a 400.
team, livemode and owner are reserved and injected by the auth middleware.
Show child attributes
Show child attributes
"MXN"
"G03"
Show child attributes
Show child attributes
01, 02, 03, 04, 05, 06, 08, 12, 13, 14, 15, 17, 23, 24, 25, 26, 27, 28, 29, 30, 31, 99 "03"
PPD, PUE "PUE"
Return base64 encoded PDF and XML files in response
true
Exchange rate for currency conversion. If not provided, the latest rate from our rates collection will be used automatically.
1
123
"A"
Your identifier for this invoice, for example your order id. With it, sending the same request again cannot issue a second CFDI or charge a second credit:
- Once the invoice exists, the same key answers
400withduplicate: trueand the existinguuid. - While another request with the key is being processed, it answers
409idempotency_in_progress. - After a
503PAC_OUTCOME_UNKNOWN, a retry with the key resends the exact same XML and folio, so the PAC either stamps it once or reports the stamp it already made. - A definitive rejection (for example the SAT refusing the data) frees the key, so you can fix the body and send it again under the same key.
Scoped to your team and the credential's mode. Required on every item of POST /invoices/income/batch.
"unique_key_123"
01, 02, 03, 04, null "01"
Show child attributes
Show child attributes
Show child attributes
Show child attributes
"Additional notes for PDF"
"<addenda>...</addenda>"
Whether to send the document via email to the client. Defaults to true.
true
Suppress all notification emails for this document. Takes precedence over
send_email — when true, no mail is sent even if send_email is true.
false
["client@example.com"]
Optional. Invoice automation type:
payment: Create invoice with payment automationnone: No automation, create invoice only
payment, none "payment"
Show child attributes
Show child attributes