interface WeposClientOptions { /** API key del integrador (wpk_test_… = Sandbox, wpk_live_… = Producción). */ apiKey: string; /** Base URL de la instalación WePOS. Default: https://pos.wecodecr.com */ baseUrl?: string; /** Timeout por request en ms. Default: 30000. */ timeoutMs?: number; /** Reintentos ante 429 / 5xx / errores de red. Default: 2. */ maxRetries?: number; /** Implementación de fetch (para entornos sin fetch global o para tests). */ fetch?: typeof fetch; } interface RequestOptions { method: 'GET' | 'POST' | 'PATCH' | 'DELETE'; path: string; query?: Record; body?: unknown; /** Idempotency-Key: reintentar con la misma key no duplica el comprobante. */ idempotencyKey?: string; signal?: AbortSignal; } declare class HttpClient { private readonly apiKey; private readonly baseUrl; private readonly timeoutMs; private readonly maxRetries; private readonly fetchImpl; constructor(opts: WeposClientOptions); private buildUrl; request(opts: RequestOptions): Promise; /** Backoff exponencial con jitter; respeta Retry-After si viene. */ private backoff; } /** * Tipos del SDK de WePOS. * * Estos tipos están curados a mano para la mejor DX, pero reflejan fielmente el * esquema OpenAPI publicado en `/api/v1/openapi`. Para la superficie completa de * la API (incluyendo endpoints internos) puedes regenerar `openapi.d.ts` con * `npm run gen:types` (ver README). */ type HaciendaEnv = 'STAGING' | 'PRODUCTION'; /** Estado de procesamiento en Hacienda. `null` = aún sin respuesta. */ type HaciendaStatus = 'indeterminado' | 'aceptado' | 'rechazado'; /** Estado interno del comprobante. */ type DocumentStatus = 'DRAFT' | 'SIGNED' | 'SUBMITTED' | 'ACCEPTED' | 'REJECTED' | 'ERROR'; type IdType = 'CEDULA_FISICA' | 'CEDULA_JURIDICA' | 'DIMEX' | 'NITE' | 'EXTRANJERO_NO_DOMICILIADO' | 'NO_CONTRIBUYENTE'; type PaymentMethod = 'CASH' | 'CARD' | 'CHECK' | 'TRANSFER' | 'COLLECTED' | 'SINPE_MOVIL' | 'DIGITAL' | 'CREDIT' | 'OTHER'; type IssuableDocumentType = 'FE' | 'TE'; type DocumentType = 'FE' | 'TE' | 'NC' | 'ND' | 'FEC' | 'FEE'; interface ApiMeta { requestId: string; cursor?: number | string | null; nextCursor?: number | string | null; } interface ApiEnvelope { data: T | null; error: { code: string; message: string; details?: Record; } | null; meta: ApiMeta; } interface InvoiceLineInput { description: string; quantity: number; unitPrice: number; /** Código CABYS de 13 dígitos. */ cabysCode: string; /** Unidad de medida (default `Sp` servicio / `Unid`). */ unitCode?: string; /** Default 13. `0` = exento. */ taxPercent?: number; discount?: number; } interface InvoiceCustomerInput { /** Id de un cliente existente, o use idType+idNumber+name. */ id?: string; idType?: IdType; idNumber?: string; name?: string; email?: string; } interface CreateInvoiceInput { documentType: IssuableDocumentType; /** Requerido para FE. */ customer?: InvoiceCustomerInput; currency?: string; exchangeRate?: number; /** Condición de venta v4.4 (ej. '01' contado). */ saleCondition?: string; paymentMethod?: PaymentMethod; notes?: string; branchId?: string; /** * CodigoActividadEmisor: con cuál actividad económica del EMISOR se emite, * cuando el emisor tiene varias registradas en Hacienda. Si se omite, se usa * la actividad principal. Debe ser una actividad registrada del emisor. */ activityCode?: string; /** * CodigoActividadReceptor (opcional, v4.4): actividad económica del COMPRADOR. * Útil cuando el receptor la requiere para su crédito fiscal. Obtené las * actividades del receptor con `reference.getTaxpayer(idNumber)`. */ receptorActivityCode?: string; lines: InvoiceLineInput[]; } /** Respuesta de emisión (POST /invoices). El comprobante queda encolado. */ interface CreatedInvoice { id: string; documentType: DocumentType; status: DocumentStatus; environment: HaciendaEnv; total: number; message: string; } /** Detalle de un comprobante (GET /invoices/{id}). */ interface Invoice { id: string; documentType: DocumentType; status: DocumentStatus; environment: HaciendaEnv; claveNumerica: string | null; consecutivo: string | null; haciendaStatus: HaciendaStatus | null; haciendaMessage: string | null; contingency: boolean; currency: string; subtotal: number; discountTotal: number; taxTotal: number; total: number; emissionDate: string; customer: { idType: IdType; idNumber: string; name: string; } | null; } /** Item del listado de comprobantes (GET /invoices). */ interface InvoiceListItem { id: string; documentType: DocumentType; status: DocumentStatus; environment: HaciendaEnv; haciendaStatus: HaciendaStatus | null; claveNumerica: string | null; total: number; currency: string; emissionDate: string; } interface InvoiceXml { id: string; clave: string | null; haciendaStatus: HaciendaStatus | null; signedXml: string | null; responseXml: string | null; } interface ListInvoicesParams { limit?: number; documentType?: DocumentType; } interface CreditNoteInput { reason?: string; /** true = reversa total del comprobante. */ fullReversal?: boolean; /** Devolución parcial por línea. */ lines?: Array<{ lineNumber: number; quantity: number; }>; } type DebitNoteReferenceCode = '01' | '02' | '04' | '05' | '06' | '07' | '08' | '09' | '10' | '11' | '12' | '13' | '14' | '15' | '16' | '99'; interface DebitNoteInput { reason: string; /** CodigoReferencia v4.4 (default '04'; '03' no es válido). */ referenceCode?: DebitNoteReferenceCode; lines: InvoiceLineInput[]; } interface ExportInvoiceInput { currency: string; exchangeRate: number; receptor: { name: string; foreignId: string; addressAbroad?: string; email?: string; }; saleCondition?: string; branchId?: string; notes?: string; lines: InvoiceLineInput[]; } interface CreateCustomerInput { idType: IdType; idNumber: string; name: string; email?: string; phone?: string; address?: string; } interface ListCustomersParams { limit?: number; search?: string; } interface ListProductsParams { limit?: number; search?: string; } interface ListInventoryParams { limit?: number; productId?: string; warehouseId?: string; search?: string; } interface Customer { id: string; idType: IdType; idNumber: string; name: string; email: string | null; phone: string | null; /** Presente al crear (POST). */ createdAt?: string; } interface Product { id: string; sku: string | null; barcode: string | null; name: string; cabysCode: string | null; salePrice: number; unitCode: string | null; isActive: boolean; } interface InventoryItem { productId: string; variantId: string | null; productName: string | null; sku: string | null; warehouseId: string; warehouseName: string | null; quantity: number; reservedQuantity: number; available: number; minStock: number; updatedAt: string; } interface Branch { id: string; name: string; code: string; province: string | null; canton: string | null; district: string | null; isMain: boolean; } interface CabysSearchParams { /** Código de 13 dígitos a validar (retorna tarifa de IVA). */ code?: string; /** Texto de búsqueda (mín. 3 caracteres). */ q?: string; top?: number; } interface CabysItem { codigo: string; descripcion: string; /** Tarifa de IVA en porcentaje. */ impuesto: number; categorias?: string[]; } interface TaxpayerActivity { codigo: string; descripcion: string; tipo: string; } interface Taxpayer { identificacion: string; nombre: string; tipoIdentificacion: string; regimen: string | null; estado: string | null; moroso: boolean; omiso: boolean; actividades: TaxpayerActivity[]; } interface Exoneration { numeroDocumento: string; tipoDocumento: unknown; nombreInstitucion: string | null; fechaEmision: string | null; fechaVencimiento: string | null; porcentajeExoneracion: number; cabys: string[]; } interface IssueOptions { /** Reintentar con la misma key no duplica el comprobante. */ idempotencyKey?: string; } interface IssueAndWaitOptions extends IssueOptions { /** Tiempo máximo de espera por la respuesta de Hacienda (ms). Default 60000. */ timeoutMs?: number; /** Intervalo entre consultas de estado (ms). Default 2000. */ pollIntervalMs?: number; } declare class InvoicesResource { private readonly http; constructor(http: HttpClient); /** Emite un comprobante FE/TE. Responde de inmediato (queda encolado). */ create(input: CreateInvoiceInput, opts?: IssueOptions): Promise; /** Consulta el estado y detalle de un comprobante. */ get(id: string): Promise; /** Lista comprobantes (más recientes primero). */ list(params?: ListInvoicesParams): Promise; /** Obtiene el XML firmado + la respuesta de Hacienda. */ getXml(id: string): Promise; /** Emite una Nota de Crédito (NC) sobre un comprobante. */ createCreditNote(invoiceId: string, input: CreditNoteInput, opts?: IssueOptions): Promise; /** Emite una Nota de Débito (ND) sobre un comprobante. */ createDebitNote(invoiceId: string, input: DebitNoteInput, opts?: IssueOptions): Promise; /** Emite una Factura de Exportación (FEE, código 09). */ export(input: ExportInvoiceInput, opts?: IssueOptions): Promise; /** * Emite un comprobante y espera (poll) hasta que Hacienda lo acepte o rechace. * El ciclo fiscal es asíncrono: este helper hace POST /invoices y luego * consulta GET /invoices/{id} hasta un estado terminal o el timeout. * * @throws WeposTimeoutError si Hacienda no responde dentro de timeoutMs. */ issueAndWait(input: CreateInvoiceInput, opts?: IssueAndWaitOptions): Promise; } declare class CustomersResource { private readonly http; constructor(http: HttpClient); /** Crea o actualiza un cliente (receptor). Scope: customers:write. */ create(input: CreateCustomerInput): Promise; /** Lista clientes. Scope: customers:read. */ list(params?: ListCustomersParams): Promise; } declare class ProductsResource { private readonly http; constructor(http: HttpClient); /** Lista productos del catálogo. Scope: products:read. */ list(params?: ListProductsParams): Promise; } declare class InventoryResource { private readonly http; constructor(http: HttpClient); /** Existencias por bodega. Scope: inventory:read. */ list(params?: ListInventoryParams): Promise; } declare class BranchesResource { private readonly http; constructor(http: HttpClient); /** Lista sucursales del tenant (para conocer el branchId). Scope: branches:read. */ list(): Promise; } /** Consultas de referencia contra Hacienda. Scope: reference:read. */ declare class ReferenceResource { private readonly http; constructor(http: HttpClient); /** Valida un código CABYS de 13 dígitos (retorna tarifa de IVA). */ getCabys(code: string): Promise; /** Busca CABYS por texto (mín. 3 caracteres). */ searchCabys(q: string, top?: number): Promise; /** Búsqueda flexible: por `code` (valida uno) o por `q` (lista). */ cabys(params: CabysSearchParams): Promise; /** Valida un contribuyente por cédula en Hacienda. */ getTaxpayer(id: string): Promise; /** Consulta una exoneración por número de autorización en la DGT. */ getExoneration(autorizacion: string): Promise; } /** Datos para aprovisionar un tenant fiscal desde un SaaS partner. */ interface ProvisionTenantInput { /** Nombre / razón social del negocio. */ name: string; idType: 'CEDULA_FISICA' | 'CEDULA_JURIDICA' | 'DIMEX' | 'NITE' | 'EXTRANJERO_NO_DOMICILIADO'; idNumber: string; /** Correo del usuario admin del tenant (dueño técnico). */ adminEmail: string; adminName?: string; tradeName?: string; /** Correo de contacto del negocio (default: adminEmail). */ email?: string; phone?: string; businessType?: 'PULPERIA' | 'RESTAURANTE' | 'RETAIL' | 'SERVICIOS' | 'COMPLETO'; /** * Ubicación de la casa matriz. Preferí los **códigos** de Hacienda (provincia 1 * dígito, cantón y distrito 2 dígitos, ej. `{ province: '1', canton: '01', * district: '01' }`). También se aceptan los **nombres oficiales** * (`'San José'/'Central'/'Carmen'`), que WePOS resuelve al código. */ location: { province: string; canton: string; district: string; address?: string; }; activities?: Array<{ codigo: string; descripcion?: string; tipo?: string; }>; /** Devolver una API key de datos para emitir por este tenant (default: true). */ issueApiKey?: boolean; } interface ProvisionedTenant { tenantId: string; adminUserId: string; branchId: string; environment: 'STAGING' | 'PRODUCTION'; /** API key de datos (`wpk_…`) para emitir por este tenant. Solo si issueApiKey !== false. */ tenantApiKey?: string; } interface PartnerTenantSummary { id: string; name: string; idType: string; idNumber: string; planStatus: string; haciendaEnv: string; createdAt: string; } interface SetCredentialsInput { /** Default: el environment de la partner key. */ environment?: 'STAGING' | 'PRODUCTION'; user?: string; password?: string; } interface UploadCertificateInput { /** Default: el environment de la partner key. */ environment?: 'STAGING' | 'PRODUCTION'; /** El .p12 codificado en base64. */ p12Base64: string; pin: string; } interface TenantConfig { id: string; name: string; idType: string; idNumber: string; defaultEnvironment: 'STAGING' | 'PRODUCTION'; planStatus: string; activities: Array<{ code: string; description: string; isPrimary: boolean; isActive: boolean; }>; environments: Array<{ environment: string; hasCredentials: boolean; hasCertificate: boolean; certExpiresAt: string | null; }>; } interface UpdateTenantConfigInput { /** Promover el ambiente por defecto del tenant (STAGING → PRODUCTION). */ defaultEnvironment?: 'STAGING' | 'PRODUCTION'; /** Reemplaza los códigos de actividad económica del tenant. */ activities?: Array<{ codigo: string; descripcion?: string; tipo?: string; }>; } /** Tipo de comprobante Hacienda de un contador de consecutivos (los 10 tipos). */ type ConsecutiveDocumentType = 'FE' | 'ND' | 'NC' | 'TE' | 'CCE' | 'CPCE' | 'RCE' | 'FEC' | 'FEE' | 'REP'; interface ConsecutiveCounter { branchCode: string; terminalCode: string; documentType: ConsecutiveDocumentType; /** Último número emitido (string por ser hasta 10 dígitos). */ lastNumber: string; /** Consecutivo completo (20 dígitos) que tendría el PRÓXIMO comprobante. */ nextConsecutivo: string; } interface SetConsecutivesInput { /** Default: el environment de la partner key. */ environment?: 'STAGING' | 'PRODUCTION'; /** * Contadores a fijar. `value` es el ÚLTIMO número ya emitido en el sistema * anterior: si el negocio venía en la 400, poné `value: 400` y el próximo * comprobante saldrá 401. Debe ser ≥ el valor actual (nunca se retrocede). */ counters: Array<{ branchCode: string; terminalCode: string; documentType: ConsecutiveDocumentType; value: number | string; }>; } interface SetConsecutivesResult { tenantId: string; environment: string; updated: ConsecutiveCounter[]; count: number; } interface TenantApiKeyInfo { id: string; name: string; environment: 'STAGING' | 'PRODUCTION'; /** Prefijo público no secreto (ej. `wpk_test_ab12cd34`). */ prefix: string; scopes: string[]; lastUsedAt: string | null; expiresAt: string | null; revokedAt: string | null; createdAt: string; } interface IssueKeyInput { /** Default: el environment de la partner key. `wpk_test_` (STAGING) o `wpk_live_` (PRODUCTION). */ environment?: 'STAGING' | 'PRODUCTION'; name?: string; scopes?: string[]; } interface IssuedKey { tenantId: string; environment: string; /** La data key (`wpk_…`) en texto plano. Se devuelve UNA sola vez, no se puede recuperar. */ tenantApiKey: string; key: { id: string; name: string; environment: string; prefix: string; scopes: string[]; }; } declare class PartnerTenantsResource { private readonly http; constructor(http: HttpClient); /** Aprovisiona un tenant fiscal completo (owned por el partner). Requiere partner key. */ create(input: ProvisionTenantInput): Promise; /** Lista los tenants que este partner aprovisionó. */ list(): Promise<{ tenants: PartnerTenantSummary[]; }>; /** Configura las credenciales ATV de Hacienda del tenant, por ambiente. */ setCredentials(tenantId: string, input: SetCredentialsInput): Promise<{ tenantId: string; environment: string; updated: boolean; }>; /** Sube el certificado de firma (.p12 en base64) del tenant, por ambiente. */ uploadCertificate(tenantId: string, input: UploadCertificateInput): Promise<{ tenantId: string; environment: string; certExpiresAt: string | null; }>; /** Lee la config fiscal del tenant + estado de credenciales/cert por ambiente. */ get(tenantId: string): Promise; /** Actualiza la config: promover ambiente por defecto y/o reemplazar actividades. */ update(tenantId: string, input: UpdateTenantConfigInput): Promise<{ tenantId: string; updated: boolean; }>; /** Lee los consecutivos del tenant por ambiente (default: el de la partner key). */ getConsecutives(tenantId: string, environment?: 'STAGING' | 'PRODUCTION'): Promise<{ environment: string; counters: ConsecutiveCounter[]; }>; /** * Fija el consecutivo de arranque (migración desde otro sistema). Aplica todos * los contadores de forma ATÓMICA. El nuevo valor debe ser ≥ el actual. */ setConsecutives(tenantId: string, input: SetConsecutivesInput): Promise; /** Lista las data keys (`wpk_…`) del tenant (solo metadatos, nunca el secreto). */ listKeys(tenantId: string): Promise<{ keys: TenantApiKeyInfo[]; }>; /** * Emite una nueva data key (`wpk_…`) para el tenant, por ambiente. Sirve para * mover un tenant EXISTENTE entre sandbox y producción sin recrearlo: pedí una * key con `environment: 'STAGING'` para obtener una `wpk_test_` y emitir en * sandbox aunque el tenant se haya creado bajo una partner key live. El * plaintext se devuelve UNA sola vez. */ issueKey(tenantId: string, input?: IssueKeyInput): Promise; /** Revoca una data key del tenant (inmediato e irreversible). */ revokeKey(tenantId: string, keyId: string): Promise<{ tenantId: string; keyId: string; revoked: boolean; }>; } /** * Superficie del plano de control para SaaS partner. Se usa con una PARTNER key * (`wppk_…`), no una key de tenant. Tras crear un tenant, usá el `tenantApiKey` * devuelto en un nuevo `WeposClient` para emitir por ese tenant. */ declare class PartnerResource { readonly tenants: PartnerTenantsResource; constructor(http: HttpClient); } /** * Cliente del SDK de WePOS. * * @example * const wepos = new WeposClient({ apiKey: 'wpk_live_...' }) * const invoice = await wepos.invoices.issueAndWait({ * documentType: 'FE', * customer: { idType: 'CEDULA_JURIDICA', idNumber: '3101123456', name: 'Cliente S.A.' }, * lines: [{ description: 'Consultoría', quantity: 1, unitPrice: 25000, cabysCode: '8314300000000' }], * }) * console.log(invoice.claveNumerica, invoice.haciendaStatus) */ declare class WeposClient { readonly invoices: InvoicesResource; readonly customers: CustomersResource; readonly products: ProductsResource; readonly inventory: InventoryResource; readonly branches: BranchesResource; readonly reference: ReferenceResource; /** Plano de control para SaaS partner (requiere partner key `wppk_…`). */ readonly partner: PartnerResource; constructor(options: WeposClientOptions); } /** * Error tipado que lanza el SDK ante cualquier respuesta no exitosa de la API. * Expone el `code` estable de WePOS (ej. 'VALIDATION_ERROR', 'RATE_LIMITED'), * el status HTTP, el requestId (para soporte) y los detalles de validación. */ declare class WeposApiError extends Error { readonly code: string; readonly status: number; readonly requestId?: string; readonly details?: Record; constructor(params: { code: string; message: string; status: number; requestId?: string; details?: Record; }); /** ¿El error es por límite de tasa (429)? */ get isRateLimit(): boolean; /** ¿Es un error de autenticación / autorización? */ get isAuth(): boolean; } /** Se lanza cuando issueAndWait agota el tiempo esperando la respuesta de Hacienda. */ declare class WeposTimeoutError extends Error { readonly invoiceId: string; constructor(invoiceId: string, message: string); } export { type ApiEnvelope, type ApiMeta, type Branch, type CabysItem, type CabysSearchParams, type ConsecutiveCounter, type ConsecutiveDocumentType, type CreateCustomerInput, type CreateInvoiceInput, type CreatedInvoice, type CreditNoteInput, type Customer, type DebitNoteInput, type DebitNoteReferenceCode, type DocumentStatus, type DocumentType, type Exoneration, type ExportInvoiceInput, type HaciendaEnv, type HaciendaStatus, type IdType, type InventoryItem, type Invoice, type InvoiceCustomerInput, type InvoiceLineInput, type InvoiceListItem, type InvoiceXml, type IssuableDocumentType, type IssueAndWaitOptions, type IssueKeyInput, type IssueOptions, type IssuedKey, type ListCustomersParams, type ListInventoryParams, type ListInvoicesParams, type ListProductsParams, type PartnerTenantSummary, type PaymentMethod, type Product, type ProvisionTenantInput, type ProvisionedTenant, type RequestOptions, type SetConsecutivesInput, type SetConsecutivesResult, type SetCredentialsInput, type Taxpayer, type TaxpayerActivity, type TenantApiKeyInfo, type TenantConfig, type UpdateTenantConfigInput, type UploadCertificateInput, WeposApiError, WeposClient, type WeposClientOptions, WeposTimeoutError };