Ejemplos ejecutables de SDK
Fragmentos vinculados a su fuente
Sección titulada «Fragmentos vinculados a su fuente»Estos ejemplos se extraen durante el build desde los ficheros de código SDK delimitados por marcadores estables. La documentación no mantiene una copia manual adicional del código.
Control de emisión
El ejemplo de primera factura valida antes de emitir y exige confirmación explícita del llamador y una clave de idempotencia. No lo ejecutes contra Production.
Primera factura
var draft = await client.Invoices.CreateDraftAsync( new CreateInvoiceDraftRequest { CustomerId = Required("EMISSARY_CUSTOMER_ID"), SeriesId = Required("EMISSARY_SERIES_ID"), Currency = "EUR", IssueDate = DateOnly.FromDateTime(DateTime.UtcNow), Lines = [ new InvoiceLineRequest { Description = "Software development service", Quantity = 1, Unit = "service", UnitPrice = 100m, DiscountType = "None", DiscountValue = 0, TaxRateId = Required("EMISSARY_TAX_RATE_ID") } ] }, idempotencyKey: Required("EMISSARY_DRAFT_IDEMPOTENCY_KEY"));
var validation = await client.Invoices.ValidateAsync(draft.Id); Console.WriteLine($"Draft {draft.Id}: valid={validation.IsValid}"); foreach (var error in validation.Errors) { Console.WriteLine($"Validation: {error}"); }
if (!validation.IsValid || !string.Equals(Environment.GetEnvironmentVariable("EMISSARY_CONFIRM_ISSUE"), "true", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("No invoice was issued. Set EMISSARY_CONFIRM_ISSUE=true to explicitly authorize the example issue call."); return; }
var issued = await client.Invoices.IssueAsync( draft.Id, new IssueInvoiceRequest { ExpectedVersion = draft.Version }, idempotencyKey: Required("EMISSARY_ISSUE_IDEMPOTENCY_KEY")); Console.WriteLine($"Issued {issued.InvoiceNumber ?? issued.Id}; fiscal status: {issued.FiscalSubmissionStatus ?? issued.FiscalStatus ?? "not reported"}."); //const client = createClient();const customer = await client.customers.create({ type: "Business", legalName: requiredEnv("EMISSARY_CUSTOMER_LEGAL_NAME"), countryCode: requiredEnv("EMISSARY_CUSTOMER_COUNTRY"), defaultCurrency: "EUR", preferredLocale: "en", billingAddress: { line1: requiredEnv("EMISSARY_CUSTOMER_ADDRESS"), city: requiredEnv("EMISSARY_CUSTOMER_CITY"), countryCode: requiredEnv("EMISSARY_CUSTOMER_COUNTRY") },}, { idempotencyKey: requiredEnv("EMISSARY_CUSTOMER_IDEMPOTENCY_KEY") });if (!customer.id) throw new Error("The API did not return the customer ID.");
const draft = await client.invoices.createDraft({ customerId: customer.id, seriesId: requiredEnv("EMISSARY_SERIES_ID"), currency: "EUR", lines: [{ description: "Development service", quantity: 1, unitPrice: 100, taxRateId: requiredEnv("EMISSARY_TAX_RATE_ID") }],}, { idempotencyKey: requiredEnv("EMISSARY_DRAFT_IDEMPOTENCY_KEY") });if (!draft.id) throw new Error("The API did not return the draft ID.");const validation = await client.invoices.validate(draft.id);if (!validation.isValid) throw new Error(`Draft is invalid: ${(validation.errors ?? []).join("; ")}`);
if (process.env.EMISSARY_CONFIRM_ISSUE === "true") { await client.invoices.issue(draft.id, { expectedVersion: draft.version }, requiredEnv("EMISSARY_ISSUE_IDEMPOTENCY_KEY")); console.log(`Issued invoice ${draft.id}.`);} else { console.log(`Validated draft ${draft.id}. Set EMISSARY_CONFIRM_ISSUE=true to explicitly issue it.`);}//from __future__ import annotations
import osfrom datetime import date
from emissary import ( CreateInvoiceDraftRequest, EmissaryClient, InvoiceLineRequest, IssueInvoiceRequest,)
def required(name: str) -> str: value = os.environ.get(name, "").strip() if not value: raise SystemExit(f"Set {name} before running this example.") return value
with EmissaryClient( api_key=required("EMISSARY_API_KEY"), environment_id=required("EMISSARY_ENVIRONMENT_ID"), base_url=required("EMISSARY_BASE_URL"),) as client: draft = client.invoices.create_draft( CreateInvoiceDraftRequest( customer_id=required("EMISSARY_CUSTOMER_ID"), series_id=required("EMISSARY_SERIES_ID"), currency=os.environ.get("EMISSARY_CURRENCY", "EUR"), issue_date=date.today().isoformat(), lines=[ InvoiceLineRequest( description="Integration service", quantity=1, unit_price=float(required("EMISSARY_UNIT_PRICE")), tax_rate_id=required("EMISSARY_TAX_RATE_ID"), ) ], ), idempotency_key=os.environ.get("EMISSARY_DRAFT_IDEMPOTENCY_KEY"), ) if not draft.id: raise RuntimeError("The API did not return the draft ID.") validation = client.invoices.validate(draft.id) if not validation.is_valid: raise RuntimeError(f"Draft is not valid: {validation.errors}")
confirmation = input(f"Issue invoice {draft.id}? Type ISSUE to confirm: ") if confirmation != "ISSUE": print(f"Draft {draft.id} remains unissued.") else: result = client.invoices.issue( draft.id, IssueInvoiceRequest(expected_version=draft.version), idempotency_key=required("EMISSARY_ISSUE_IDEMPOTENCY_KEY"), ) print(f"Issued invoice {result.invoice_number or result.id} ({result.status}).")#Estado fiscal
var status = await client.Invoices.GetFiscalStatusAsync(Required("EMISSARY_INVOICE_ID")); Console.WriteLine($"Invoice {status.InvoiceId}: commercial={status.CommercialStatus}, fiscal={status.FiscalStatus}"); if (status.LatestOperation is { } operation) { Console.WriteLine($"Operation {operation.Id}: {operation.Status}; code={operation.LatestErrorCode ?? "none"}"); } //const client = createClient();const status = await client.invoices.getFiscalStatus(requiredEnv("EMISSARY_INVOICE_ID"));console.log(status.fiscalStatus, status.latestOperation?.status ?? "No fiscal operation");if (status.latestOperation?.id) { const operation = await client.fiscalOperations.get(status.latestOperation.id); console.log(operation.providerCode, operation.latestErrorCode, operation.latestErrorExcerpt);}//from __future__ import annotations
import os
from emissary import EmissaryClient
def required(name: str) -> str: value = os.environ.get(name, "").strip() if not value: raise SystemExit(f"Set {name} before running this example.") return value
with EmissaryClient( api_key=required("EMISSARY_API_KEY"), environment_id=required("EMISSARY_ENVIRONMENT_ID"), base_url=required("EMISSARY_BASE_URL"),) as client: status = client.invoices.get_fiscal_status(required("EMISSARY_INVOICE_ID")) operation = status.latest_operation print(f"Invoice: {status.invoice_id}; fiscal status: {status.fiscal_status}") if operation: print(f"Operation: {operation.id}; status: {operation.status}; provider:") print(operation.provider_code)#Descargar un documento
var invoiceId = Required("EMISSARY_INVOICE_ID"); var documentId = Required("EMISSARY_DOCUMENT_ID"); await using var download = await client.Documents.DownloadAsync(invoiceId, documentId); var destination = download.FileName ?? $"{documentId}.bin"; await using var file = File.Create(destination); await download.Content.CopyToAsync(file); Console.WriteLine($"Saved {destination} ({download.ContentType ?? "unknown content type"})."); //const client = createClient();const invoiceId = requiredEnv("EMISSARY_INVOICE_ID");const documentId = requiredEnv("EMISSARY_DOCUMENT_ID");const metadata = await client.documents.getMetadata(invoiceId, documentId);const download = await client.documents.download(invoiceId, documentId);const reader = download.body.getReader();try { for (;;) { const { done, value } = await reader.read(); if (done) break; process.stdout.write(value); }} finally { reader.releaseLock();}console.error(`Downloaded ${metadata.fileName ?? download.fileName ?? "document"} (${download.contentType ?? "unknown type"}).`);//from __future__ import annotations
import osfrom pathlib import Path
from emissary import EmissaryClient
def required(name: str) -> str: value = os.environ.get(name, "").strip() if not value: raise SystemExit(f"Set {name} before running this example.") return value
destination = Path(required("EMISSARY_OUTPUT_PATH")).expanduser()with EmissaryClient( api_key=required("EMISSARY_API_KEY"), environment_id=required("EMISSARY_ENVIRONMENT_ID"), base_url=required("EMISSARY_BASE_URL"),) as client: with client.documents.download( required("EMISSARY_INVOICE_ID"), required("EMISSARY_DOCUMENT_ID") ) as document: with destination.open("wb") as output: for chunk in document.iter_bytes(): output.write(chunk) print(f"Downloaded {destination}.")#Verificación de webhook
var secret = Required("EMISSARY_WEBHOOK_SECRET"); var timestamp = Required("WEBHOOK-TIMESTAMP"); var signature = Required("WEBHOOK-SIGNATURE"); using var body = new MemoryStream(); await Console.OpenStandardInput().CopyToAsync(body);
var verified = EmissaryWebhookVerifier.Verify(body.ToArray(), timestamp, signature, secret); Console.WriteLine(verified ? "Webhook signature verified." : "Webhook signature is invalid or outside the timestamp tolerance."); //const chunks: Buffer[] = [];for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk));const rawBody = Buffer.concat(chunks);const valid = verifyWebhookSignature(rawBody, { timestamp: requiredEnv("WEBHOOK-TIMESTAMP"), signature: requiredEnv("WEBHOOK-SIGNATURE"),}, requiredEnv("EMISSARY_WEBHOOK_SECRET"));if (!valid) throw new Error("Webhook signature is invalid or expired.");const event = parseWebhookEvent<{ id: string; type: string }>(rawBody);console.log(event.id, event.type);//from __future__ import annotations
import osimport sys
from emissary import parse_webhook_event, verify_webhook_signature
secret = os.environ.get("EMISSARY_WEBHOOK_SECRET", "")timestamp = os.environ.get("EMISSARY_WEBHOOK_TIMESTAMP")signature = os.environ.get("EMISSARY_WEBHOOK_SIGNATURE")raw_body = sys.stdin.buffer.read()if not verify_webhook_signature(raw_body, timestamp=timestamp, signature=signature, secret=secret): raise SystemExit("Webhook signature verification failed.")event = parse_webhook_event(raw_body)print(f"Verified event: {event.get('id', '<unknown>')}")#