# Crear un producto

`POST https://api.fiscalisto.com/v1/products`

Un producto o servicio del catálogo del emisor, con su clave del SAT, su unidad, su precio y sus impuestos, para usarlo en items con product.

## Parámetros

| Nombre | Dónde | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `Idempotency-Key` | encabezado |  | Opcional (los SDK la mandan solos). Si la respuesta se pierde, repita la solicitud con el mismo valor durante 24 horas: contesta lo mismo, con idempotent-replayed: true, y no lo hace dos veces (ni crea, ni manda correos, ni cobra). |

## Cuerpo

| Campo | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `issuer` | string |  | Emisor (iss_…). Si la llave tiene un solo emisor o la cuenta tiene uno solo, puede omitirse. |
| `name` | string o null |  | Nombre corto para encontrarlo, solo para usted; en el CFDI va description. |
| `description` | string | sí | Descripción. (hasta 1000 caracteres) |
| `product_key` | string | sí | Clave del producto o servicio (ClaveProdServ), 8 dígitos de c_ClaveProdServ. Búsquela con GET /v1/sat_catalogs/product_keys?q=… |
| `unit_key` | string |  | Clave de unidad (ClaveUnidad) de c_ClaveUnidad: E48 unidad de servicio (por omisión), H87 pieza, ACT actividad… (hasta 5 caracteres) |
| `unit_name` | string o null |  | Nombre de la unidad (Unidad), hasta 20 caracteres. |
| `sku` | string o null |  | Número de identificación o SKU (NoIdentificacion). |
| `unit_price` | number |  | Precio unitario antes de impuestos (ValorUnitario). (de 0 a 1000000000000) |
| `open_price` | boolean |  | Precio abierto: sin precio fijo (una noche de hotel que cambia cada día); cada factura manda su unit_price. |
| `taxability` | `01`, `02`, `03`, `04`, `05`, `06`, `07`, `08` |  | Objeto de impuesto (ObjetoImp), c_ObjetoImp: 01 no objeto, 02 sí objeto (por omisión), 03 sin desglose, 04 no causa… |
| `iva` | `0`, `0.16`, `0.08`, `exento` |  | Tasa de IVA trasladado: 0.16 (por omisión), 0.08 (región fronteriza), 0 o exento. |
| `ieps` | number o null |  | IEPS trasladado: tasa (0.265…) o cuota en pesos por unidad, según ieps_factor. |
| `ieps_factor` | `Tasa`, `Cuota` |  | Tasa o Cuota (TipoFactor del IEPS). |
| `iva_retention` | number |  | Tasa de IVA retenido (por ejemplo 0.106667, dos terceras partes del 16%). (de 0 a 0.16) |
| `isr_retention` | number |  | Tasa de ISR retenido (por ejemplo 0.10 honorarios, 0.0125 RESICO). (de 0 a 0.35) |
| `local_taxes` | arreglo de objeto |  | Impuestos locales que lleva, como el ISH 3% de hospedaje: van en cada factura con él, sobre sus conceptos. (hasta 20) |
| `local_taxes[].retention` | boolean | sí | true si es una retención local; false si es un traslado. |
| `local_taxes[].name` | string | sí | Nombre del impuesto local (ImpLocTrasladado o ImpLocRetenido), como ISH. (hasta 100 caracteres) |
| `local_taxes[].rate` | number | sí | Tasa en por ciento (TasadeTraslado o TasadeRetencion). (de -∞ a 100) |
| `track_stock` | boolean |  | Lleva existencias (Inventario): cada factura que lo vende las saca del almacén de su sucursal, y una cancelada las regresa. Ver GET /v1/products/{id}/stock. |
| `cost` | number o null |  | Su costo por unidad en pesos sin IVA, hasta que sus compras den otro: vale las existencias que entran sin unit_cost. |
| `barcode` | string o null |  | Código de barras (EAN, UPC o el suyo). Una factura cuyo concepto lo trae como NoIdentificacion saca existencias de este producto. |
| `min_stock` | number o null |  | Existencia mínima: por debajo, el aviso de existencias bajas lo incluye. |

Ejemplo:

```json
{
  "description": "Mensualidad",
  "product_key": "86121700",
  "sku": "MEN-1",
  "unit_price": 2500
}
```

## Con el SDK de TypeScript

```ts
import { Fiscalisto } from "fiscalisto";

// La llave viene de FISCALISTO_API_KEY.
const fiscalisto = new Fiscalisto();

const product = await fiscalisto.products.create({
  description: "Mensualidad",
  product_key: "86121700",
  sku: "MEN-1",
  unit_price: 2500,
}, { idempotencyKey: "pedido-A-1042" });
```

## Con el SDK de Python

```python
from fiscalisto import Fiscalisto

# La llave viene de FISCALISTO_API_KEY.
fiscalisto = Fiscalisto()

product = fiscalisto.products.create({
    "description": "Mensualidad",
    "product_key": "86121700",
    "sku": "MEN-1",
    "unit_price": 2500,
}, idempotency_key="pedido-A-1042")
```

## Con el SDK de PHP

```php
<?php

use Fiscalisto\Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
$fiscalisto = new Fiscalisto();

$product = $fiscalisto->products->create([
    'description' => 'Mensualidad',
    'product_key' => '86121700',
    'sku' => 'MEN-1',
    'unit_price' => 2500,
], ['idempotency_key' => 'pedido-A-1042']);
```

## Con el SDK de .NET

```csharp
using Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var product = await fiscalisto.Products.CreateAsync(new CreateProductParams
{
    Description = "Mensualidad",
    ProductKey = "86121700",
    Sku = "MEN-1",
    UnitPrice = 2500,
}, new RequestOptions { IdempotencyKey = "pedido-A-1042" });
```

## Con el SDK de Go

```go
package main

import (
	"context"
	"fmt"
	"log"

	fiscalisto "fiscalisto.com/go"
)

func main() {
	// La llave viene de FISCALISTO_API_KEY.
	client, err := fiscalisto.NewClient("")
	if err != nil {
		log.Fatal(err)
	}
	ctx := context.Background()

	product, err := client.Products.Create(ctx, &fiscalisto.CreateProductParams{
		Description: "Mensualidad",
		ProductKey:  "86121700",
		SKU:         fiscalisto.String("MEN-1"),
		UnitPrice:   fiscalisto.Float64(2500),
	}, fiscalisto.WithIdempotencyKey("pedido-A-1042"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(product.ID)
}
```

## Con el SDK de Java

```java
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.RequestOptions;
import com.fiscalisto.model.CreateProductParams;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var product = fiscalisto.products().create(new CreateProductParams()
        .setDescription("Mensualidad")
        .setProductKey("86121700")
        .setSku("MEN-1")
        .setUnitPrice(2500), RequestOptions.idempotencyKey("pedido-A-1042"));
System.out.println(product.getId());
```

## Respuesta 201

Correcto.

Un objeto `Product`:

| Campo | Tipo | Siempre viene | Descripción |
| --- | --- | --- | --- |
| `id` | string | sí | Identificador del objeto, con su prefijo (iss_, inv_, ret_, cus_, prd_, emp_, bat_, brn_, whs_, stm_, adj_, evt_, whe_). |
| `livemode` | boolean | sí | true en producción (llaves fk_live_), false en pruebas (fk_test_). Lo de pruebas no vale ante el SAT. |
| `object` | `"product"` | sí | Qué tipo de objeto es («invoice», «customer»…). |
| `issuer` | string | sí | El emisor (iss_…). |
| `name` | string o null | sí | Nombre corto para encontrarlo, solo para usted. |
| `description` | string | sí | Descripción que va en el CFDI (Descripcion). |
| `product_key` | string | sí | Clave del producto o servicio (ClaveProdServ), 8 dígitos de c_ClaveProdServ. Búsquela con GET /v1/sat_catalogs/product_keys?q=… |
| `unit_key` | string | sí | Clave de unidad (ClaveUnidad) de c_ClaveUnidad: E48 unidad de servicio (por omisión), H87 pieza, ACT actividad… |
| `unit_name` | string o null | sí | Nombre de la unidad (Unidad), hasta 20 caracteres. |
| `sku` | string o null | sí | Número de identificación o SKU (NoIdentificacion). |
| `unit_price` | number | sí | Precio unitario antes de impuestos (ValorUnitario). |
| `open_price` | boolean | sí | Precio abierto: el producto no tiene precio fijo y cada concepto con él manda su unit_price. |
| `taxability` | string | sí | Objeto de impuesto (ObjetoImp), c_ObjetoImp: 01 no objeto, 02 sí objeto (por omisión), 03 sin desglose, 04 no causa… |
| `iva` | string | sí | Tasa de IVA trasladado: 0.16 (por omisión), 0.08 (región fronteriza), 0 o exento. |
| `ieps` | number o null | sí | IEPS trasladado: tasa (0.265…) o cuota en pesos por unidad, según ieps_factor. |
| `ieps_factor` | string o null | sí | Tasa o Cuota (TipoFactor del IEPS). |
| `iva_retention` | number | sí | Tasa de IVA retenido (por ejemplo 0.106667, dos terceras partes del 16%). |
| `isr_retention` | number | sí | Tasa de ISR retenido (por ejemplo 0.10 honorarios, 0.0125 RESICO). |
| `local_taxes` | arreglo de objeto | sí | Impuestos locales (complemento implocal): traslados y retenciones estatales. |
| `local_taxes[].retention` | boolean | sí | true si es una retención local; false si es un traslado. |
| `local_taxes[].name` | string | sí | Nombre del impuesto local (ImpLocTrasladado o ImpLocRetenido), como ISH. |
| `local_taxes[].rate` | number | sí | Tasa en por ciento (TasadeTraslado o TasadeRetencion). |
| `track_stock` | boolean | sí | true si lleva existencias (Inventario). |
| `cost` | number o null | sí | Su costo por unidad en pesos sin IVA, o null. |
| `barcode` | string o null | sí | Su código de barras, o null. |
| `min_stock` | number o null | sí | Su existencia mínima, o null. |
| `created_at` | string (date-time) | sí | Cuándo se creó, ISO 8601 con la hora de la Ciudad de México (-06:00). |
| `updated_at` | string (date-time) o null | sí | Cuándo cambió por última vez, ISO 8601 (-06:00). |

```json
{
  "id": "prd_OufpKqnrvx9p1",
  "object": "product",
  "livemode": false,
  "issuer": "iss_OufpKqnrvx9p",
  "name": null,
  "description": "Mensualidad",
  "product_key": "86121700",
  "unit_key": "E48",
  "unit_name": "Unidad de servicio",
  "sku": "MEN-1",
  "unit_price": 2500,
  "open_price": false,
  "taxability": "02",
  "iva": "0.16",
  "ieps": null,
  "ieps_factor": null,
  "iva_retention": 0,
  "isr_retention": 0,
  "local_taxes": [],
  "track_stock": false,
  "cost": null,
  "barcode": null,
  "min_stock": null,
  "created_at": "2026-10-20T09:02:11-06:00",
  "updated_at": "2026-10-24T10:15:42-06:00"
}
```

## Errores

Puede responder 400, 401, 403, 404, 429, 500 con el cuerpo de error de siempre; cada código está en https://fiscalisto.com/docs/api/errores.md.
