> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usatimbre.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Invoice (Full)

> Create an invoice from a receipt image in a single call, with automatic member creation

## Overview

Create an invoice from a receipt image in a single call. Provide complete tax info to use an existing member by RFC or automatically create a new member profile.

Supports JSON (with base64 image) or `multipart/form-data` (with file upload).

<Note>
  **This operation requires 1 credit.** Credits are consumed from the API key owner, not the member profile.
</Note>

## Authentication

Requires a valid API key with:

* API key owner belongs to an organization
* `api_keys_enabled` feature flag enabled for the organization

## Request Body

<ParamField body="tax_info" type="object" required>
  Tax information object

  <Expandable title="tax_info properties">
    <ParamField body="tax_id" type="string" required>
      RFC (Registro Federal de Contribuyentes, 12-13 characters). Example: `XAXX010101000`
    </ParamField>

    <ParamField body="cfdi_use" type="string" required>
      CFDI usage code. Common values:

      * `G01` - Adquisición de mercancías
      * `G02` - Devoluciones, descuentos o bonificaciones
      * `G03` - Gastos en general
      * `S01` - Sin efectos fiscales
    </ParamField>

    <ParamField body="fiscal_regimen" type="string" required>
      Tax regime code (e.g., `601`, `612`, `626`).
    </ParamField>

    <ParamField body="taxpayer" type="string" required>
      Full name or business name.
    </ParamField>

    <ParamField body="postal_code" type="string" required>
      Fiscal postal code.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="receipt_image" type="string" required>
  Receipt image as a base64 data URL (e.g., `data:image/jpeg;base64,/9j/4AAQ...`). When using `multipart/form-data`, send as a file upload instead.
</ParamField>

<ParamField body="email" type="string">
  Contact email address
</ParamField>

<ParamField body="phone_number" type="string">
  Phone number (e.g., `+525512345678`, `4431041040`)
</ParamField>

<ParamField body="expense_description" type="string">
  Short description of the expense (max 50 characters)
</ParamField>

## Behavior

1. Validates the API key, organization, feature flag, and input fields
2. Looks up the RFC in the caller's organization:
   * **Found** — uses the existing profile
   * **Not found** — creates a new member profile with the provided tax data, then submits the invoice
3. Resolves the tax regime for the invoice:
   * If `fiscal_regimen` is in the request, uses it (validated against member's regimes)
   * If the member has a single regime, uses it automatically
   * If the member has multiple regimes and the provided value is not valid, returns `400`
4. Checks credits on the API key owner
5. Submits the invoice to the invoicing provider
6. Returns the invoice, member, and whether a new profile was created

## Response

<ResponseField name="success" type="boolean">
  Whether the request was successful
</ResponseField>

<ResponseField name="data" type="object">
  Response data object

  <Expandable title="data properties">
    <ResponseField name="invoice" type="object">
      Invoice submitted to the invoicing provider

      <Expandable title="invoice properties">
        <ResponseField name="id" type="string">
          Invoice tracking ID (e.g., `inv_abc123`)
        </ResponseField>

        <ResponseField name="status" type="string">
          Always `processing` on creation
        </ResponseField>

        <ResponseField name="amount" type="number">
          Populated once the invoice is processed (initially `null`)
        </ResponseField>

        <ResponseField name="currency" type="string">
          Always `MXN`
        </ResponseField>

        <ResponseField name="vendor" type="string">
          Populated once the receipt is analyzed (initially `null`)
        </ResponseField>

        <ResponseField name="member_rfc" type="string">
          RFC used for this invoice
        </ResponseField>

        <ResponseField name="created_at" type="string">
          ISO 8601 creation timestamp
        </ResponseField>

        <ResponseField name="pdf_url" type="string">
          Populated once the CFDI is stamped (initially `null`)
        </ResponseField>

        <ResponseField name="xml_url" type="string">
          Populated once the CFDI is stamped (initially `null`)
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="member" type="object">
      Profile used (existing or newly created)

      <Expandable title="member properties">
        <ResponseField name="id" type="string">
          Profile UUID
        </ResponseField>

        <ResponseField name="name" type="string">
          Full name or business name
        </ResponseField>

        <ResponseField name="email" type="string">
          Email address (`null` if not provided)
        </ResponseField>

        <ResponseField name="phone_number" type="string">
          Phone number (`null` if not provided)
        </ResponseField>

        <ResponseField name="tax_id" type="string">
          RFC
        </ResponseField>

        <ResponseField name="org_id" type="string">
          Organization ID
        </ResponseField>

        <ResponseField name="created_at" type="string">
          Profile creation timestamp
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="created_profile" type="boolean">
      `true` if a new profile was created, `false` if an existing one was used
    </ResponseField>

    <ResponseField name="credits_remaining" type="number">
      API key owner's remaining credits after this operation
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash Existing RFC theme={null}
  curl -X POST https://api.usatimbre.com/api/timbre/create-invoice-full \
    -H "Authorization: Bearer tmb_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "tax_info": {
        "tax_id": "XAXX010101000",
        "cfdi_use": "G03",
        "taxpayer": "Juan Pérez García",
        "postal_code": "06600",
        "fiscal_regimen": "612"
      },
      "receipt_image": "data:image/jpeg;base64,/9j/4AAQ..."
    }'
  ```

  ```bash New RFC (creates profile) theme={null}
  curl -X POST https://api.usatimbre.com/api/timbre/create-invoice-full \
    -H "Authorization: Bearer tmb_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "tax_info": {
        "tax_id": "XAXX010101000",
        "cfdi_use": "G03",
        "taxpayer": "Juan Pérez García",
        "postal_code": "06600",
        "fiscal_regimen": "612"
      },
      "receipt_image": "data:image/jpeg;base64,/9j/4AAQ...",
      "email": "juan@example.com",
      "phone_number": "+5214431041040"
    }'
  ```

  ```python Python theme={null}
  import requests
  import base64

  # Read and encode image
  with open('receipt.jpg', 'rb') as f:
      image_base64 = base64.b64encode(f.read()).decode('utf-8')

  response = requests.post(
      'https://api.usatimbre.com/api/timbre/create-invoice-full',
      headers={
          'Authorization': 'Bearer tmb_your_api_key',
          'Content-Type': 'application/json'
      },
      json={
          'tax_info': {
              'tax_id': 'XAXX010101000',
              'cfdi_use': 'G03',
              'taxpayer': 'Juan Pérez García',
              'postal_code': '06600',
              'fiscal_regimen': '612'
          },
          'receipt_image': f'data:image/jpeg;base64,{image_base64}'
      }
  )
  result = response.json()
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true,
    "data": {
      "invoice": {
        "id": "inv_abc123",
        "status": "processing",
        "amount": null,
        "currency": "MXN",
        "vendor": null,
        "member_rfc": "XAXX010101000",
        "created_at": "2024-01-21T10:30:00Z",
        "pdf_url": null,
        "xml_url": null
      },
      "member": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "Juan Pérez",
        "email": "juan@example.com",
        "phone_number": "+525512345678",
        "tax_id": "XAXX010101000",
        "org_id": "org_123456",
        "created_at": "2024-01-21T10:00:00Z"
      },
      "created_profile": true,
      "credits_remaining": 9
    }
  }
  ```

  ```json 400 Missing fields theme={null}
  {
    "success": false,
    "error": {
      "code": "MISSING_REQUIRED_FIELDS",
      "message": "Missing required fields: tax_id, cfdi_use, fiscal_regimen, taxpayer, postal_code, receipt_image"
    }
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "success": false,
    "error": {
      "code": "INVALID_API_KEY",
      "message": "API key not found"
    }
  }
  ```

  ```json 403 No credits theme={null}
  {
    "success": false,
    "error": {
      "code": "INSUFFICIENT_CREDITS",
      "message": "No credits remaining"
    }
  }
  ```

  ```json 404 RFC not found theme={null}
  {
    "success": false,
    "error": {
      "code": "RFC_NOT_FOUND",
      "message": "RFC not found in organization"
    }
  }
  ```
</ResponseExample>

## Error Codes

| Status | Code                        | Description                                                                                   |
| ------ | --------------------------- | --------------------------------------------------------------------------------------------- |
| 400    | `MISSING_REQUIRED_FIELDS`   | Missing `tax_id`, `cfdi_use`, `fiscal_regimen`, `taxpayer`, `postal_code`, or `receipt_image` |
| 400    | `INVALID_RFC_FORMAT`        | RFC doesn't match Mexican format (12-13 chars)                                                |
| 400    | `INVALID_TAX_REGIME`        | Invalid fiscal regime code                                                                    |
| 400    | `INVALID_CFDI_FOR_REGIME`   | CFDI usage code not valid for the resolved regime                                             |
| 400    | `INVALID_REGIME`            | Specified regime not in the member's registered regimes                                       |
| 400    | `INVALID_EMAIL`             | Email format is invalid                                                                       |
| 400    | `INVALID_PHONE_NUMBER`      | Phone number format is invalid                                                                |
| 401    | —                           | Missing API key                                                                               |
| 401    | `INVALID_API_KEY`           | API key not found                                                                             |
| 403    | `NO_ORGANIZATION`           | API key owner has no organization                                                             |
| 403    | `FEATURE_DISABLED`          | `api_keys_enabled` not active for the organization                                            |
| 403    | `INSUFFICIENT_CREDITS`      | No credits remaining                                                                          |
| 404    | `RFC_NOT_FOUND`             | RFC not found in organization                                                                 |
| 500    | `LOOKUP_ERROR`              | Error looking up RFC                                                                          |
| 500    | `AUTH_USER_CREATION_FAILED` | Failed to create auth user for new profile                                                    |
| 500    | `PROFILE_CREATION_FAILED`   | Failed to create profile record                                                               |
| 500    | `TAX_INFO_CREATION_FAILED`  | Failed to create tax info record                                                              |
| 500    | `INTERNAL_ERROR`            | Unexpected server error                                                                       |
| 503    | `SERVICE_UNAVAILABLE`       | Invoicing provider is temporarily unavailable                                                 |
