fiskit

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 11, 2026 License: MIT Imports: 18 Imported by: 0

README

FisKit for Go

Español más abajo

Official client of the FisKit API: Argentine electronic invoices with ARCA (formerly AFIP) in a single request. Go 1.21 or later, standard library only.

go get github.com/fiskitapp/fiskit-go
import "github.com/fiskitapp/fiskit-go"

client, err := fiskit.New("") // reads FISKIT_API_KEY

// Your sale id as the key: a retry never issues a second invoice
invoice, err := client.Invoices.Create(ctx, map[string]any{
	"voucher_type": "invoice_c",
	"amounts":      map[string]any{"total": 1500},
}, "sale-8812")
if err != nil {
	var apiErr *fiskit.Error
	if errors.As(err, &apiErr) {
		log.Printf("%s: %s", apiErr.Code, apiErr.Message) // branch on Code, it is stable
	}
	return err
}
if invoice.Pending() {
	// ARCA was slow: FisKit finishes it in the background. Store invoice.ID and wait for the webhook.
}
fmt.Println(*invoice.Number, invoice.CAE)

pdf, err := client.Invoices.PDF(ctx, invoice.ID)                    // PDF with ARCA's QR code
_, err = client.Invoices.Email(ctx, invoice.ID, "customer@example.com")
taxpayer, err := client.Taxpayers.Retrieve(ctx, 30712345671)       // name and VAT condition of a CUIT

Webhooks:

http.HandleFunc("/webhooks/fiskit", func(w http.ResponseWriter, r *http.Request) {
	body, _ := io.ReadAll(r.Body)
	event, err := fiskit.VerifyWebhook(body, r.Header, os.Getenv("FISKIT_WEBHOOK_SECRET"))
	if err != nil {
		http.Error(w, "invalid signature", http.StatusBadRequest)
		return
	}
	// event.Type == "invoice.authorized"; event.Data.Object is the invoice
	w.WriteHeader(http.StatusNoContent)
})

Options: fiskit.WithHTTPClient, fiskit.WithMaxRetries and fiskit.WithBaseURL. Every call takes a context.Context.

sk_test_... keys issue against ARCA's homologation environment (no fiscal value); sk_live_... keys issue real invoices. Outages are retried with the same idempotency key.

Full documentation: https://fiskit.com.ar/developers

Coding with an AI agent? Point it to https://fiskit.com.ar/llms.txt: the API rules, errors and examples in plain text.


Español

Cliente oficial de la API de FisKit: facturas electrónicas de ARCA (ex AFIP) con un solo pedido. Para Go 1.21 o superior, sin dependencias.

client, err := fiskit.New("") // lee FISKIT_API_KEY

// Con el id de tu venta como clave, un reintento nunca duplica la factura
factura, err := client.Invoices.Create(ctx, map[string]any{
	"voucher_type": "invoice_c",
	"amounts":      map[string]any{"total": 1500},
}, "venta-8812")

Los errores de la API son *fiskit.Error, con Code, Message, Param y RequestID. Para los webhooks, fiskit.VerifyWebhook verifica la firma y devuelve el evento.

Las claves sk_test_... emiten en homologación, sin validez fiscal; las sk_live_... emiten facturas reales.

Documentación completa: https://fiskit.com.ar/developers

¿Programás con un agente de IA? Pasale https://fiskit.com.ar/llms.txt: las reglas, errores y ejemplos de la API en texto plano.

Documentation

Overview

Package fiskit is the official Go client for the FisKit API: Argentine electronic invoices with ARCA (formerly AFIP) in a single request. It has no dependencies besides the standard library.

client, err := fiskit.New("") // reads FISKIT_API_KEY
invoice, err := client.Invoices.Create(ctx, map[string]any{
	"voucher_type": "invoice_c",
	"amounts":      map[string]any{"total": 1500},
}, "order-8812")

Index

Constants

View Source
const DefaultWebhookTolerance = 5 * time.Minute

DefaultWebhookTolerance is how old a delivery may be before it is rejected.

View Source
const Version = "0.1.1"

Version of this library, sent in the User-Agent header.

Variables

View Source
var ErrInvalidWebhook = errors.New("fiskit: invalid webhook")

ErrInvalidWebhook is returned (wrapped) when a delivery cannot be trusted.

Functions

This section is empty.

Types

type Address

type Address struct {
	Street     string `json:"street"`
	City       string `json:"city"`
	Province   string `json:"province"`
	PostalCode string `json:"postal_code"`
}

Address is a fiscal address from the ARCA registry.

type AuthorityMessage

type AuthorityMessage struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

AuthorityMessage is an observation or error returned by ARCA.

type Client

type Client struct {
	Invoices  *InvoicesService
	Taxpayers *TaxpayersService
	// contains filtered or unexported fields
}

Client talks to the FisKit API. It is safe for concurrent use.

func New

func New(apiKey string, opts ...Option) (*Client, error)

New creates a client. apiKey is sk_test_... or sk_live_...; when empty, FISKIT_API_KEY is used.

type Error

type Error struct {
	Status    int
	Type      string
	Code      string
	Message   string
	Param     string
	RequestID string
	Body      []byte
}

Error is an error answered by the API, or a network failure (Status 0, Code "network"). Branch on Code, which is stable; Message is meant for people.

func (*Error) Error

func (e *Error) Error() string

type Event

type Event struct {
	ID       string    `json:"id"`
	Object   string    `json:"object"`
	Type     string    `json:"type"` // invoice.authorized, invoice.rejected or invoice.failed
	Created  time.Time `json:"created"`
	Livemode bool      `json:"livemode"`
	Data     struct {
		Object Invoice `json:"object"`
	} `json:"data"`
}

Event is a webhook delivery. Data.Object is the invoice with the same fields as the API response.

func VerifyWebhook

func VerifyWebhook(rawBody []byte, header http.Header, secret string) (*Event, error)

VerifyWebhook checks the Standard Webhooks signature of a delivery and returns the event. Pass the raw body exactly as received, before decoding it, and the secret (whsec_...) from the dashboard.

func VerifyWebhookAt

func VerifyWebhookAt(rawBody []byte, header http.Header, secret string, now time.Time, tolerance time.Duration) (*Event, error)

VerifyWebhookAt is VerifyWebhook with an explicit clock and tolerance.

type Invoice

type Invoice struct {
	ID                    string             `json:"id"`
	Object                string             `json:"object"`
	Status                string             `json:"status"` // pending, processing, authorized, rejected, reconciling or failed
	VoucherType           string             `json:"voucher_type"`
	PointOfSale           int                `json:"point_of_sale"`
	Number                *int64             `json:"number"` // nil until authorized
	CAE                   string             `json:"cae"`
	CAEDueDate            string             `json:"cae_due_date"` // YYYY-MM-DD
	AuthorityObservations []AuthorityMessage `json:"authority_observations"`
	AuthorityErrors       []AuthorityMessage `json:"authority_errors"`
	Raw                   map[string]any     `json:"-"`
}

Invoice is an invoice as the API returns it. Raw holds every field of the response.

func (*Invoice) Authorized

func (i *Invoice) Authorized() bool

Authorized reports whether ARCA authorized the invoice (it has a number and a CAE).

func (*Invoice) Pending

func (i *Invoice) Pending() bool

Pending reports whether FisKit is still working on it: look it up later or wait for the webhook.

type InvoicesService

type InvoicesService struct {
	// contains filtered or unexported fields
}

InvoicesService issues and looks up invoices.

func (*InvoicesService) Create

func (s *InvoicesService) Create(ctx context.Context, body any, idempotencyKey string) (*Invoice, error)

Create issues an invoice. body is any value that encodes to the request JSON (a map or a struct).

Pass your own idempotencyKey, for example your sale id: retrying with it never issues a second invoice. When empty, one is generated so the automatic retries are still safe.

A 202 is not an error: the returned invoice is Pending and FisKit finishes it in the background.

func (*InvoicesService) Email

func (s *InvoicesService) Email(ctx context.Context, id, email string) (string, error)

Email sends the PDF to the customer and returns the address it went to. With an empty email it goes to the receiver.email of the invoice.

func (*InvoicesService) PDF

func (s *InvoicesService) PDF(ctx context.Context, id string) ([]byte, error)

PDF returns the voucher PDF, in ARCA's layout and with its QR code.

func (*InvoicesService) Retrieve

func (s *InvoicesService) Retrieve(ctx context.Context, id string) (*Invoice, error)

Retrieve looks up an invoice by id, for example after a 202.

type Option

type Option func(*Client)

Option customizes a Client.

func WithBaseURL

func WithBaseURL(url string) Option

WithBaseURL points the client to another address, for example a mock in tests.

func WithHTTPClient

func WithHTTPClient(httpClient *http.Client) Option

WithHTTPClient replaces the HTTP client (timeouts, proxies, instrumentation).

func WithMaxRetries

func WithMaxRetries(n int) Option

WithMaxRetries sets how many times a failed request is retried (2 by default). Only requests that are safe to repeat are retried: GETs and POSTs with an idempotency key.

type Taxpayer

type Taxpayer struct {
	CUIT                   int64          `json:"cuit"`
	Name                   string         `json:"name"`
	Type                   string         `json:"type"` // person or company
	Active                 bool           `json:"active"`
	VATCondition           string         `json:"vat_condition"`
	ReceiverVATConditionID int            `json:"receiver_vat_condition_id"` // send it as receiver.vat_condition_id
	MonotributoCategory    *string        `json:"monotributo_category"`
	Address                *Address       `json:"address"`
	Raw                    map[string]any `json:"-"`
}

Taxpayer is a CUIT as the ARCA registry describes it.

type TaxpayersService

type TaxpayersService struct {
	// contains filtered or unexported fields
}

TaxpayersService queries the ARCA registry.

func (*TaxpayersService) Retrieve

func (s *TaxpayersService) Retrieve(ctx context.Context, cuit int64) (*Taxpayer, error)

Retrieve returns the name, address and VAT condition of a CUIT.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL