curl --request POST \
--url https://api.gigstack.io/v2/clients \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Juan Pérez García",
"email": "juan.perez@ejemplo.com",
"company": "Empresa SA de CV",
"phone": "+52 55 1234 5678",
"legal_name": "Juan Pérez García",
"tax_id": "PEGJ800101ABC",
"use": "G03",
"tax_system": "601",
"address": {
"country": "MEX",
"street": "Av. Insurgentes Sur",
"zip": "03100",
"city": "Ciudad de México",
"state": "CDMX",
"exterior": "123",
"interior": "4B",
"municipality": "Benito Juárez",
"neighborhood": "Del Valle"
},
"bcc": [
"admin@empresa.com"
],
"metadata": {
"custom_field": "value",
"department": "sales"
},
"defaults": {
"keep_full_legal_name": false,
"issue_automatic_invoices": false,
"issue_invoiceable_receipts": true
},
"search": {
"on_key": "tax_id",
"on_value": "PEGJ800101ABC",
"update": false
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Juan Pérez García',
email: 'juan.perez@ejemplo.com',
company: 'Empresa SA de CV',
phone: '+52 55 1234 5678',
legal_name: 'Juan Pérez García',
tax_id: 'PEGJ800101ABC',
use: 'G03',
tax_system: '601',
address: {
country: 'MEX',
street: 'Av. Insurgentes Sur',
zip: '03100',
city: 'Ciudad de México',
state: 'CDMX',
exterior: '123',
interior: '4B',
municipality: 'Benito Juárez',
neighborhood: 'Del Valle'
},
bcc: ['admin@empresa.com'],
metadata: {custom_field: 'value', department: 'sales'},
defaults: {
keep_full_legal_name: false,
issue_automatic_invoices: false,
issue_invoiceable_receipts: true
},
search: {on_key: 'tax_id', on_value: 'PEGJ800101ABC', update: false}
})
};
fetch('https://api.gigstack.io/v2/clients', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.gigstack.io/v2/clients"
payload = {
"name": "Juan Pérez García",
"email": "juan.perez@ejemplo.com",
"company": "Empresa SA de CV",
"phone": "+52 55 1234 5678",
"legal_name": "Juan Pérez García",
"tax_id": "PEGJ800101ABC",
"use": "G03",
"tax_system": "601",
"address": {
"country": "MEX",
"street": "Av. Insurgentes Sur",
"zip": "03100",
"city": "Ciudad de México",
"state": "CDMX",
"exterior": "123",
"interior": "4B",
"municipality": "Benito Juárez",
"neighborhood": "Del Valle"
},
"bcc": ["admin@empresa.com"],
"metadata": {
"custom_field": "value",
"department": "sales"
},
"defaults": {
"keep_full_legal_name": False,
"issue_automatic_invoices": False,
"issue_invoiceable_receipts": True
},
"search": {
"on_key": "tax_id",
"on_value": "PEGJ800101ABC",
"update": False
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"message": "Existing client found",
"data": {
"id": "client_1234567890",
"name": "Juan Pérez García",
"email": "juan.perez@ejemplo.com",
"tax_id": "PEGJ800101ABC",
"tax_system": "601",
"legal_name": "Juan Pérez García",
"address": {
"street": "Av. Insurgentes Sur 123",
"zip": "03100",
"city": "Ciudad de México",
"state": "CDMX",
"country": "MEX"
},
"is_valid": true,
"livemode": true,
"created_at": 1677651234,
"team": "team_1234567890",
"owner": "user_1234567890",
"from": "api"
}
}Create client
Integration note: Creating a contact does not establish fiscal validity. Inspect fiscal_validation when returned; contact-only input can produce status skipped. A matching search with update false returns the existing customer with HTTP 200; a new record returns 201. 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 client with fiscal information for Mexican tax compliance.
Duplicate Prevention (Upsert): Use the search parameter to find existing clients before creating:
- If a match is found and
search.updateisfalse(default): Returns the existing client without modifications. - If a match is found and
search.updateistrue: Updates the existing client with the provided data and returns it. - If no match is found: Creates a new client.
This is useful for integrations that may send the same client multiple times.
gigstack Connect: Create clients for other teams using the team parameter.
curl --request POST \
--url https://api.gigstack.io/v2/clients \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Juan Pérez García",
"email": "juan.perez@ejemplo.com",
"company": "Empresa SA de CV",
"phone": "+52 55 1234 5678",
"legal_name": "Juan Pérez García",
"tax_id": "PEGJ800101ABC",
"use": "G03",
"tax_system": "601",
"address": {
"country": "MEX",
"street": "Av. Insurgentes Sur",
"zip": "03100",
"city": "Ciudad de México",
"state": "CDMX",
"exterior": "123",
"interior": "4B",
"municipality": "Benito Juárez",
"neighborhood": "Del Valle"
},
"bcc": [
"admin@empresa.com"
],
"metadata": {
"custom_field": "value",
"department": "sales"
},
"defaults": {
"keep_full_legal_name": false,
"issue_automatic_invoices": false,
"issue_invoiceable_receipts": true
},
"search": {
"on_key": "tax_id",
"on_value": "PEGJ800101ABC",
"update": false
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Juan Pérez García',
email: 'juan.perez@ejemplo.com',
company: 'Empresa SA de CV',
phone: '+52 55 1234 5678',
legal_name: 'Juan Pérez García',
tax_id: 'PEGJ800101ABC',
use: 'G03',
tax_system: '601',
address: {
country: 'MEX',
street: 'Av. Insurgentes Sur',
zip: '03100',
city: 'Ciudad de México',
state: 'CDMX',
exterior: '123',
interior: '4B',
municipality: 'Benito Juárez',
neighborhood: 'Del Valle'
},
bcc: ['admin@empresa.com'],
metadata: {custom_field: 'value', department: 'sales'},
defaults: {
keep_full_legal_name: false,
issue_automatic_invoices: false,
issue_invoiceable_receipts: true
},
search: {on_key: 'tax_id', on_value: 'PEGJ800101ABC', update: false}
})
};
fetch('https://api.gigstack.io/v2/clients', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.gigstack.io/v2/clients"
payload = {
"name": "Juan Pérez García",
"email": "juan.perez@ejemplo.com",
"company": "Empresa SA de CV",
"phone": "+52 55 1234 5678",
"legal_name": "Juan Pérez García",
"tax_id": "PEGJ800101ABC",
"use": "G03",
"tax_system": "601",
"address": {
"country": "MEX",
"street": "Av. Insurgentes Sur",
"zip": "03100",
"city": "Ciudad de México",
"state": "CDMX",
"exterior": "123",
"interior": "4B",
"municipality": "Benito Juárez",
"neighborhood": "Del Valle"
},
"bcc": ["admin@empresa.com"],
"metadata": {
"custom_field": "value",
"department": "sales"
},
"defaults": {
"keep_full_legal_name": False,
"issue_automatic_invoices": False,
"issue_invoiceable_receipts": True
},
"search": {
"on_key": "tax_id",
"on_value": "PEGJ800101ABC",
"update": False
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"message": "Existing client found",
"data": {
"id": "client_1234567890",
"name": "Juan Pérez García",
"email": "juan.perez@ejemplo.com",
"tax_id": "PEGJ800101ABC",
"tax_system": "601",
"legal_name": "Juan Pérez García",
"address": {
"street": "Av. Insurgentes Sur 123",
"zip": "03100",
"city": "Ciudad de México",
"state": "CDMX",
"country": "MEX"
},
"is_valid": true,
"livemode": true,
"created_at": 1677651234,
"team": "team_1234567890",
"owner": "user_1234567890",
"from": "api"
}
}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
Creation body for POST /v2/clients. name is required when creating a client.
For PUT /v2/clients/{id}, use ClientUpdateInput: an omitted name is preserved
from the existing client before validation.
Unknown top-level keys are rejected (400 validation_failed / unexpected_key);
metadata is the one object that accepts arbitrary keys. team, livemode and
owner are reserved and injected by the auth middleware.
The document_type, organization_type, tribute_code, fiscal_responsibilities,
dv and municipality_code
fields are the Colombian DIAN identification set. They are accepted for every team
regardless of country; each also accepts the empty string, which means "not set" and is
dropped before the client is stored.
"Juan Pérez García"
Search for an existing client before creating. If a match is found, the existing client is returned (or updated if update: true).
This enables upsert-like behavior to avoid duplicate clients.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
"Empresa SA de CV"
"+52 55 1234 5678"
"juan.perez@ejemplo.com"
["admin@empresa.com"]
{ "custom_field": "value" }
"Juan Pérez García"
"PEGJ800101ABC"
"G03"
"601"
Show child attributes
Show child attributes
Colombia (DIAN). Identification document code.
11 registro civil, 12 tarjeta de identidad, 13 cédula de ciudadanía,
21 tarjeta de extranjería, 22 cédula de extranjería, 31 NIT,
41 pasaporte, 42 documento de identificación extranjero,
47 PEP, 48 PPT, 50 NIT de otro país, 91 NUIP.
The empty string means "not set" and is dropped before the client is stored.
, 11, 12, 13, 21, 22, 31, 41, 42, 47, 48, 50, 91, null "31"
Colombia (DIAN). 1 = persona jurídica, 2 = persona natural.
Accepted as either a number (1, 2) or a string ("1", "2").
The empty string means "not set".
, 1, 2, null "2"
Colombia (DIAN). 01 = responsable de IVA, ZZ = no aplica.
The empty string means "not set".
, 01, ZZ, null "01"
Colombia (DIAN). Responsabilidades fiscales del cliente (lista 53).
O-13 gran contribuyente, O-15 autorretenedor,
O-23 agente de retención de IVA, O-47 régimen simple de tributación,
R-99-PN no responsable.
Omit the field (or send an empty array) to leave it unset — the client is
then reported as R-99-PN, which is also the value that applies when the
array carries only that code. R-99-PN excludes every O-* code: if both
are sent, only the O-* ones are reported.
O-13, O-15, O-23, O-47, R-99-PN ["O-15", "O-23"]
Colombia (DIAN). NIT verification digit — a single digit, or the empty string for "not set".
^[0-9]?$"7"
Colombia (DIAN). DANE municipality code — exactly five digits, or the empty string for "not set". Only meaningful for clients domiciled in Colombia.
^([0-9]{5})?$"05001"
Only applies to PUT /clients/{id}. When true (default) and the updated client passes fiscal validation, all of the client's pending receipts are automatically invoiced using the new client data. Set to false to skip this behavior.
true