Skip to main content
POST
/
v1
/
invoices
Create an invoice
curl --request POST \
  --url https://api.newinvoice.dev/v1/invoices \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "fiscal_profile_id": "fp_2P9K3sample",
  "type": "I",
  "customer": {
    "rfc": "XAXX010101000",
    "name": "PUBLICO EN GENERAL",
    "tax_regime": "616",
    "postal_code": "06000",
    "cfdi_use": "S01"
  },
  "items": [
    {
      "product_key": "01010101",
      "unit_key": "H87",
      "description": "Consultoria",
      "quantity": "1",
      "unit_price": "100.00",
      "taxes": [
        {
          "type": "IVA",
          "rate": "0.160000",
          "factor": "Tasa"
        }
      ]
    }
  ],
  "payment_form": "03",
  "payment_method": "PUE",
  "metadata": {
    "order_id": "ord_1789"
  }
}
'
import requests

url = "https://api.newinvoice.dev/v1/invoices"

payload = {
"fiscal_profile_id": "fp_2P9K3sample",
"type": "I",
"customer": {
"rfc": "XAXX010101000",
"name": "PUBLICO EN GENERAL",
"tax_regime": "616",
"postal_code": "06000",
"cfdi_use": "S01"
},
"items": [
{
"product_key": "01010101",
"unit_key": "H87",
"description": "Consultoria",
"quantity": "1",
"unit_price": "100.00",
"taxes": [
{
"type": "IVA",
"rate": "0.160000",
"factor": "Tasa"
}
]
}
],
"payment_form": "03",
"payment_method": "PUE",
"metadata": { "order_id": "ord_1789" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
fiscal_profile_id: 'fp_2P9K3sample',
type: 'I',
customer: {
rfc: 'XAXX010101000',
name: 'PUBLICO EN GENERAL',
tax_regime: '616',
postal_code: '06000',
cfdi_use: 'S01'
},
items: [
{
product_key: '01010101',
unit_key: 'H87',
description: 'Consultoria',
quantity: '1',
unit_price: '100.00',
taxes: [{type: 'IVA', rate: '0.160000', factor: 'Tasa'}]
}
],
payment_form: '03',
payment_method: 'PUE',
metadata: {order_id: 'ord_1789'}
})
};

fetch('https://api.newinvoice.dev/v1/invoices', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.newinvoice.dev/v1/invoices",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'fiscal_profile_id' => 'fp_2P9K3sample',
'type' => 'I',
'customer' => [
'rfc' => 'XAXX010101000',
'name' => 'PUBLICO EN GENERAL',
'tax_regime' => '616',
'postal_code' => '06000',
'cfdi_use' => 'S01'
],
'items' => [
[
'product_key' => '01010101',
'unit_key' => 'H87',
'description' => 'Consultoria',
'quantity' => '1',
'unit_price' => '100.00',
'taxes' => [
[
'type' => 'IVA',
'rate' => '0.160000',
'factor' => 'Tasa'
]
]
]
],
'payment_form' => '03',
'payment_method' => 'PUE',
'metadata' => [
'order_id' => 'ord_1789'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://api.newinvoice.dev/v1/invoices"

payload := strings.NewReader("{\n \"fiscal_profile_id\": \"fp_2P9K3sample\",\n \"type\": \"I\",\n \"customer\": {\n \"rfc\": \"XAXX010101000\",\n \"name\": \"PUBLICO EN GENERAL\",\n \"tax_regime\": \"616\",\n \"postal_code\": \"06000\",\n \"cfdi_use\": \"S01\"\n },\n \"items\": [\n {\n \"product_key\": \"01010101\",\n \"unit_key\": \"H87\",\n \"description\": \"Consultoria\",\n \"quantity\": \"1\",\n \"unit_price\": \"100.00\",\n \"taxes\": [\n {\n \"type\": \"IVA\",\n \"rate\": \"0.160000\",\n \"factor\": \"Tasa\"\n }\n ]\n }\n ],\n \"payment_form\": \"03\",\n \"payment_method\": \"PUE\",\n \"metadata\": {\n \"order_id\": \"ord_1789\"\n }\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.newinvoice.dev/v1/invoices")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"fiscal_profile_id\": \"fp_2P9K3sample\",\n \"type\": \"I\",\n \"customer\": {\n \"rfc\": \"XAXX010101000\",\n \"name\": \"PUBLICO EN GENERAL\",\n \"tax_regime\": \"616\",\n \"postal_code\": \"06000\",\n \"cfdi_use\": \"S01\"\n },\n \"items\": [\n {\n \"product_key\": \"01010101\",\n \"unit_key\": \"H87\",\n \"description\": \"Consultoria\",\n \"quantity\": \"1\",\n \"unit_price\": \"100.00\",\n \"taxes\": [\n {\n \"type\": \"IVA\",\n \"rate\": \"0.160000\",\n \"factor\": \"Tasa\"\n }\n ]\n }\n ],\n \"payment_form\": \"03\",\n \"payment_method\": \"PUE\",\n \"metadata\": {\n \"order_id\": \"ord_1789\"\n }\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.newinvoice.dev/v1/invoices")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"fiscal_profile_id\": \"fp_2P9K3sample\",\n \"type\": \"I\",\n \"customer\": {\n \"rfc\": \"XAXX010101000\",\n \"name\": \"PUBLICO EN GENERAL\",\n \"tax_regime\": \"616\",\n \"postal_code\": \"06000\",\n \"cfdi_use\": \"S01\"\n },\n \"items\": [\n {\n \"product_key\": \"01010101\",\n \"unit_key\": \"H87\",\n \"description\": \"Consultoria\",\n \"quantity\": \"1\",\n \"unit_price\": \"100.00\",\n \"taxes\": [\n {\n \"type\": \"IVA\",\n \"rate\": \"0.160000\",\n \"factor\": \"Tasa\"\n }\n ]\n }\n ],\n \"payment_form\": \"03\",\n \"payment_method\": \"PUE\",\n \"metadata\": {\n \"order_id\": \"ord_1789\"\n }\n}"

response = http.request(request)
puts response.read_body
{
  "object": "invoice",
  "id": "obj_2P9K3sample",
  "livemode": false,
  "status": "draft",
  "type": "I",
  "fiscal_profile_id": "fp_2P9K3sample",
  "serie": "string",
  "folio": "string",
  "customer": {
    "rfc": "XAXX010101000",
    "name": "string",
    "zip": "string",
    "tax_regime": "string",
    "use": "string"
  },
  "currency": "MXN",
  "subtotal": "116.00",
  "total": "116.00",
  "uuid": "5FB2822E-396D-4725-8521-CDC4BDD20CCF",
  "stamped_at": "2026-07-10T18:25:43Z",
  "sello_cfd": "string",
  "sello_sat": "string",
  "no_certificado_sat": "string",
  "cancellation": {
    "status": "none",
    "reason": "string",
    "substitute_invoice_id": "inv_2P9K3sample",
    "acuse_available": true
  },
  "error": "string",
  "xml_url": "https://example.com/webhooks/invoice",
  "pdf_url": "https://example.com/webhooks/invoice",
  "metadata": {},
  "fiscal_profile": {
    "object": "fiscal_profile",
    "id": "obj_2P9K3sample",
    "rfc": "XAXX010101000",
    "legal_name": "string",
    "tax_regime": "string",
    "zip": "string",
    "csd": {
      "serial": "string",
      "valid_from": "string",
      "valid_to": "string",
      "rfc": "XAXX010101000"
    },
    "status": "requires_action",
    "has_fiel": true,
    "manifest_status": "pending_signature",
    "manifest_signed_at": "2026-07-10T18:25:43Z",
    "next_actions": [
      {
        "type": "string",
        "message": "string",
        "endpoint": "string",
        "requires": [
          "string"
        ]
      }
    ],
    "pending_actions": [
      {
        "type": "string",
        "message": "string",
        "endpoint": "string",
        "requires": [
          "string"
        ]
      }
    ],
    "metadata": {},
    "brand_color": "string",
    "has_logo": true,
    "livemode": false,
    "created_at": "2026-07-10T18:25:43Z",
    "updated_at": "2026-07-10T18:25:43Z"
  },
  "created_at": "2026-07-10T18:25:43Z",
  "updated_at": "2026-07-10T18:25:43Z"
}
{
"type": "https://errors.invoiceapi.mx/auth_unauthorized",
"title": "Authentication required",
"status": 401,
"code": "auth.unauthorized",
"detail": "Missing or invalid API key.",
"remediation": "Send `Authorization: Bearer sk_test_...` (or sk_live_...) with a valid API key.",
"doc_url": "/docs/errors#auth-unauthorized",
"request_id": "req_2P9K3sample"
}
{
"type": "https://errors.invoiceapi.mx/invoice_already_stamped",
"title": "Invoice already stamped",
"status": 409,
"code": "invoice.already_stamped",
"detail": "This invoice is already stamped.",
"remediation": "Fetch the stamped invoice; do not re-stamp.",
"doc_url": "/docs/errors#invoice-already_stamped",
"request_id": "req_2P9K3sample"
}
{
"type": "https://errors.invoiceapi.mx/cfdi_invalid_input",
"title": "Invalid invoice",
"status": 422,
"code": "cfdi.invalid_input",
"detail": "items.0.unit_price: expected a decimal string.",
"remediation": "Fix every field listed in `errors` and resubmit. See /openapi.json for the schema.",
"doc_url": "/docs/errors#cfdi-invalid_input",
"request_id": "req_2P9K3sample"
}
{
"type": "https://errors.invoiceapi.mx/rate_limit_exceeded",
"title": "Rate limit exceeded",
"status": 429,
"code": "rate_limit.exceeded",
"detail": "Too many requests for this key + request class (reads and writes are limited separately).",
"remediation": "Back off and retry after the number of seconds in the Retry-After header; batch work or lower your request rate.",
"doc_url": "/docs/errors#rate_limit-exceeded",
"request_id": "req_2P9K3sample"
}
{
"type": "https://errors.invoiceapi.mx/internal_error",
"title": "Internal server error",
"status": 500,
"code": "internal.error",
"detail": "An unexpected error occurred.",
"remediation": "Retry later; contact support with the request_id if it persists.",
"doc_url": "/docs/errors#internal-error",
"request_id": "req_2P9K3sample"
}
{
"type": "https://errors.invoiceapi.mx/pac_internal_error",
"title": "PAC internal error",
"status": 502,
"code": "pac.internal_error",
"detail": "The stamping service reported a transient internal error.",
"remediation": "Retry with backoff; idempotency guards against duplicate stamps.",
"doc_url": "/docs/errors#pac-internal_error",
"request_id": "req_2P9K3sample"
}

Authorizations

Authorization
string
header
required

API key: Authorization: Bearer sk_test_... or sk_live_....

Headers

Invoice-Version
string

Pin a dated API release (Stripe-style). Omit to use the current version. An unknown value returns 400 request.invalid_version. Echoed back on every response.

Example:

"2026-07-10"

Invoice-Account
string

Connect: act on behalf of one of your connected accounts (its acct_…/org_… id). Omit to act as your own organization. Not honored on /v1/api_keys.

Example:

"org_2P9connectedacct"

Idempotency-Key
string

Safely retry any POST. The first response is stored for 24h and replayed byte-for-byte for identical retries (the replay adds an idempotent-replayed: true header). Reusing the key with a different body is 409 idempotency.key_reuse; an in-flight duplicate is 409 idempotency.key_processing. This makes retrying a 502/429 safe — no duplicate stamp.

Example:

"a1b2c3d4-e5f6-4789-8abc-1234567890ab"

Query Parameters

expand

Comma-separated related objects to inline, e.g. "fiscal_profile".

expand[]

Bracket-array form of expand, e.g. ?expand[]=fiscal_profile.

Body

application/json
fiscal_profile_id
string
required

Id of the fiscal profile (issuer) to stamp with, e.g. "fp_2P9K3sample".

Minimum string length: 1
type
enum<string>
default:I

CFDI TipoDeComprobante: "I" ingreso (default), "E" egreso (nota de crédito), "P" pago.

Available options:
I,
E,
P
serie
string

CFDI Serie (optional invoice series prefix).

Required string length: 1 - 25
folio
string

CFDI Folio; auto-assigned when omitted.

Required string length: 1 - 40
date
string

CFDI Fecha, ISO-8601; defaults to now at build time. Must be within the past 72 hours.

payment_form
enum<string>

c_FormaPago code (FormaPago), e.g. "01" efectivo, "03" transferencia, "99" por definir. Required for type I/E; forced to "99" when payment_method is PPD. See GET /v1/catalogs/payment_forms (or the SAT catalogs guide) for each code's meaning.

Available options:
01,
02,
03,
04,
05,
06,
08,
12,
13,
14,
15,
17,
23,
24,
25,
26,
27,
28,
29,
30,
31,
99
payment_method
enum<string>

c_MetodoPago: "PUE" pago en una sola exhibición or "PPD" pago en parcialidades o diferido. Required for type I/E.

Available options:
PUE,
PPD
currency
enum<string>
default:MXN

c_Moneda currency code (Moneda), e.g. "MXN" (default) or "USD". See GET /v1/catalogs/currencies (or the SAT catalogs guide) for each code's meaning.

Available options:
MXN,
USD,
EUR,
CAD,
GBP,
JPY,
CHF,
CNY,
AUD,
BRL,
ARS,
COP,
CLP,
PEN,
DKK,
SEK,
NOK,
HKD,
SGD,
NZD,
KRW,
XXX
exchange_rate

TipoCambio: MXN per 1 unit of currency; required when currency is neither MXN nor XXX.

Pattern: ^-?\d+(\.\d+)?$
use
enum<string>

c_UsoCFDI code (UsoCFDI), e.g. "G03"; falls back to customer.use. Required for type I/E. See GET /v1/catalogs/uso_cfdi (or the SAT catalogs guide) for each code's meaning.

Available options:
G01,
G02,
G03,
I01,
I02,
I03,
I04,
I05,
I06,
I07,
I08,
D01,
D02,
D03,
D04,
D05,
D06,
D07,
D08,
D09,
D10,
S01,
CP01,
CN01
export
enum<string>
default:01

c_Exportacion code (Exportacion). Default "01" (no aplica); other codes need the Comercio Exterior complement (not supported in v1). See GET /v1/catalogs/export_types (or the SAT catalogs guide) for each code's meaning.

Available options:
01,
02,
03,
04
relation
object

CFDI relation (CfdiRelacionados). Required for type E (nota de crédito).

customer
object

Customer (Receptor) — who the invoice is for.

items
object[]

Line items (Conceptos). Required for type I/E; must be empty for type P.

payments
object[]

Complemento de pagos 2.0 entries. Required for and only valid on type P.

global_information
object

InformacionGlobal for a factura global (público en general XAXX010101000).

draft
boolean

Hold the invoice as a signed draft instead of stamping it immediately (default false).

metadata
object

Integrator-owned key-value map (≤50 keys), stored and echoed back verbatim.

{key}
any

Response

Default Response

object
enum<string>
required

Always "invoice".

Available options:
invoice
id
string
required

Invoice id, e.g. "inv_2P9K3sample".

livemode
boolean
required

True if stamped with a live-mode key against the real SAT.

status
enum<string>
required

Lifecycle status: draft, stamping (in flight), stamped, or stamp_failed.

Available options:
draft,
stamping,
stamped,
stamp_failed
type
enum<string>
required

CFDI TipoDeComprobante: "I" ingreso, "E" egreso (nota de crédito), "P" pago.

Available options:
I,
E,
P
fiscal_profile_id
string
required

Id of the fiscal profile (issuer) that stamped this invoice.

serie
string | null
required

CFDI Serie, or null if unset.

folio
string | null
required

CFDI Folio, or null if unset.

customer
object
required

The receptor (customer) as stamped onto the CFDI.

currency
string
required

c_Moneda currency code, e.g. "MXN".

subtotal
string | null
required

Sum of line amounts before taxes, decimal string, e.g. "100.00".

total
string | null
required

Grand total including taxes, decimal string, e.g. "116.00".

uuid
string | null
required

SAT folio fiscal (UUID) once stamped, else null.

stamped_at
string | null
required

When the CFDI was stamped (ISO-8601 UTC), or null.

sello_cfd
string | null
required

Issuer digital seal (Sello del CFDI), or null.

sello_sat
string | null
required

SAT digital seal from the TimbreFiscalDigital, or null.

no_certificado_sat
string | null
required

SAT certificate serial that timbró the CFDI, or null.

cancellation
object
required

Cancellation status for this CFDI.

error
any | null
required

The last stamping error (problem+json shape) when status is stamp_failed, else null.

xml_url
string
required

Path to download the CFDI XML, e.g. "/v1/invoices/:id/xml".

pdf_url
string
required

Path to download the CFDI PDF, e.g. "/v1/invoices/:id/pdf".

metadata
object
required

Integrator-owned key-value map echoed back.

created_at
string
required

Creation timestamp, ISO-8601 UTC.

updated_at
string
required

Last-update timestamp, ISO-8601 UTC.

fiscal_profile
object

The full issuer profile — present only when ?expand=fiscal_profile is requested.