curl --request POST \
--url https://api.gigstack.io/v2/payments/{id}/paid \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"payment_form": "03",
"date": 1767225600000,
"ignore_emails": false
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({payment_form: '03', date: 1767225600000, ignore_emails: false})
};
fetch('https://api.gigstack.io/v2/payments/{id}/paid', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.gigstack.io/v2/payments/{id}/paid"
payload = {
"payment_form": "03",
"date": 1767225600000,
"ignore_emails": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"success": true,
"data": {
"id": "payment_1234567890",
"client": {
"id": "client_1234567890",
"name": "ESCUELA KEMPER URGATE",
"legal_name": "ESCUELA KEMPER URGATE",
"email": "contabilidad@ejemplo.com",
"bcc": [],
"phone": "+524421234567",
"tax_id": "EKU9003173C9",
"tax_system": "601",
"use": "G03",
"address": {
"street": "Av. Constituyentes",
"exterior": "1000",
"neighborhood": "Centro",
"city": "Querétaro",
"state": "QRO",
"zip": "76000",
"country": "MEX"
},
"is_valid": true,
"efos": {
"is_valid": true
},
"metadata": {},
"livemode": true,
"from": "api",
"owner": "user_1234567890",
"team": "team_1234567890",
"created_at": 1767225600000
},
"emails": [
"contabilidad@ejemplo.com"
],
"currency": "MXN",
"allowed_payment_methods": [
"card",
"bank"
],
"exchange_rate": 1,
"items": [
{
"id": "service_1234567890",
"description": "Servicios de consultoría profesional",
"quantity": 1,
"unit_price": 1000,
"product_key": "80141503",
"unit_key": "E48",
"unit_name": "Unidad de servicio",
"taxes": [
{
"type": "IVA",
"rate": 0.16,
"factor": "Tasa",
"withholding": false
}
],
"team": "team_1234567890",
"created_at": 1767225600000,
"from": "api"
}
],
"metadata": {},
"team": "team_1234567890",
"idempotency_key": "payment-2026-0001",
"from": "api",
"invoices": [
"B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
],
"livemode": true,
"owner": "user_1234567890",
"payment_form": "03",
"payments": [],
"receipts": [],
"refunds": [],
"short_url": "https://gigstack.xyz/Xk3mP9",
"success_url": null,
"status": "succeeded",
"total": 1160,
"total_refunded": 0,
"subtotal": 1000,
"taxes": 160,
"discount": 0,
"withholding_taxes": 0,
"created_at": 1767225600000,
"succeeded_at": 1767225900000,
"payment_processor": "api"
},
"message": "Payment marked as paid successfully",
"timestamp": 1767225600000
}Mark payment as paid
Mark a payment as paid with the specified payment form.
gigstack Connect: Mark other teams’ payments as paid using the team parameter.
Required Information
- payment_form (required): SAT-compliant payment form code (
01–31,99) - date (optional): when the payment was received, in Unix epoch milliseconds
(13 digits). The handler passes the value straight to
Luxon.fromMillis()and compares it againstLuxon.now().toMillis(); a seconds-based timestamp resolves to 1970 and is silently accepted. Defaults to now. A future date returns400. - send_email / ignore_emails (optional):
ignore_emailstakes precedence — the handler resolvesignore_emails ?? (send_email === false), soignore_emails: truesuppresses notifications even whensend_email: true. - amount_received (optional): cumulative amount received so far, in the payment’s
currency. Omit it, or send the full payment amount, to mark the payment
succeeded(unchanged default behavior). Send less than the full amount to record a partial top-up: the payment is set topartially_paidinstead, triggering a partial payment complement on the related PPD invoice. Requires the team’sautomatePartialPaymentComplementsdefault to be on and apayment_complementautomation already present on the payment. Sending more than the payment amount returns400.
curl --request POST \
--url https://api.gigstack.io/v2/payments/{id}/paid \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"payment_form": "03",
"date": 1767225600000,
"ignore_emails": false
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({payment_form: '03', date: 1767225600000, ignore_emails: false})
};
fetch('https://api.gigstack.io/v2/payments/{id}/paid', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.gigstack.io/v2/payments/{id}/paid"
payload = {
"payment_form": "03",
"date": 1767225600000,
"ignore_emails": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"success": true,
"data": {
"id": "payment_1234567890",
"client": {
"id": "client_1234567890",
"name": "ESCUELA KEMPER URGATE",
"legal_name": "ESCUELA KEMPER URGATE",
"email": "contabilidad@ejemplo.com",
"bcc": [],
"phone": "+524421234567",
"tax_id": "EKU9003173C9",
"tax_system": "601",
"use": "G03",
"address": {
"street": "Av. Constituyentes",
"exterior": "1000",
"neighborhood": "Centro",
"city": "Querétaro",
"state": "QRO",
"zip": "76000",
"country": "MEX"
},
"is_valid": true,
"efos": {
"is_valid": true
},
"metadata": {},
"livemode": true,
"from": "api",
"owner": "user_1234567890",
"team": "team_1234567890",
"created_at": 1767225600000
},
"emails": [
"contabilidad@ejemplo.com"
],
"currency": "MXN",
"allowed_payment_methods": [
"card",
"bank"
],
"exchange_rate": 1,
"items": [
{
"id": "service_1234567890",
"description": "Servicios de consultoría profesional",
"quantity": 1,
"unit_price": 1000,
"product_key": "80141503",
"unit_key": "E48",
"unit_name": "Unidad de servicio",
"taxes": [
{
"type": "IVA",
"rate": 0.16,
"factor": "Tasa",
"withholding": false
}
],
"team": "team_1234567890",
"created_at": 1767225600000,
"from": "api"
}
],
"metadata": {},
"team": "team_1234567890",
"idempotency_key": "payment-2026-0001",
"from": "api",
"invoices": [
"B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
],
"livemode": true,
"owner": "user_1234567890",
"payment_form": "03",
"payments": [],
"receipts": [],
"refunds": [],
"short_url": "https://gigstack.xyz/Xk3mP9",
"success_url": null,
"status": "succeeded",
"total": 1160,
"total_refunded": 0,
"subtotal": 1000,
"taxes": 160,
"discount": 0,
"withholding_taxes": 0,
"created_at": 1767225600000,
"succeeded_at": 1767225900000,
"payment_processor": "api"
},
"message": "Payment marked as paid successfully",
"timestamp": 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.
Path Parameters
Payment id.
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
SAT payment form code
01, 02, 03, 04, 05, 06, 08, 12, 13, 14, 15, 17, 23, 24, 25, 26, 27, 28, 29, 30, 31, 99 When the payment was received, as a Unix epoch timestamp in milliseconds
(13 digits). The handler feeds this value directly to Luxon.fromMillis() and
compares it to Luxon.now().toMillis(), so a seconds-precision value is
interpreted as a 1970 date rather than rejected. Defaults to now; a future
value returns 400.
1767225600000
Whether to send email notifications. Overridden by ignore_emails.
true
Suppress notification emails. Takes precedence over send_email — the handler
resolves ignore_emails ?? (send_email === false).
false
Cumulative amount received so far, in the payment's currency (not cents —
converted internally to match the payment's stored amount). Omit it, or pass
the full payment amount, to mark the payment fully succeeded (the default
behavior). Pass a value less than the payment amount to record a partial
top-up instead: the payment is set to partially_paid with this cumulative
amount, which must exceed the amount already received. A value greater than
the payment amount is rejected with 400.
Partial funding additionally requires the team's
automatePartialPaymentComplements default to be enabled and the payment to
already carry a payment_complement automation (i.e. it originated from a PPD
invoice flow) — otherwise the request is rejected with 400.
x >= 0.01500
Response
Payment marked as paid successfully. When amount_received was less than the
payment amount, the returned payment has status: partially_paid instead of
succeeded.
Standardized success envelope emitted by sendSuccessResponse.
true true
The operation payload.
Server time in epoch milliseconds (Luxon.now().toMillis()).
1767225600000
Human-readable summary. Present only when the handler supplies one.
"Operation completed successfully"