@easybits.cloud/mailmask 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +68 -12
- package/dist/index.js +61 -12
- package/dist/partner-contract.d.ts +81 -22
- package/dist/partner.d.ts +14 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -25,6 +25,7 @@ __export(index_exports, {
|
|
|
25
25
|
BALANCE_MOVEMENT_KINDS: () => BALANCE_MOVEMENT_KINDS,
|
|
26
26
|
ConflictError: () => ConflictError,
|
|
27
27
|
DOMAIN_CLAIM_TTL_DAYS: () => DOMAIN_CLAIM_TTL_DAYS,
|
|
28
|
+
DailyLimitError: () => DailyLimitError,
|
|
28
29
|
EXTERNAL_ID_RE: () => EXTERNAL_ID_RE,
|
|
29
30
|
FALLBACK_LABEL_RE: () => FALLBACK_LABEL_RE,
|
|
30
31
|
ForbiddenError: () => ForbiddenError,
|
|
@@ -52,6 +53,7 @@ __export(index_exports, {
|
|
|
52
53
|
PARTNER_TOPUP_MAX_CENTS: () => PARTNER_TOPUP_MAX_CENTS,
|
|
53
54
|
PARTNER_TOPUP_MIN_CENTS: () => PARTNER_TOPUP_MIN_CENTS,
|
|
54
55
|
PARTNER_WEBHOOK_EVENTS: () => PARTNER_WEBHOOK_EVENTS,
|
|
56
|
+
PARTNER_WELCOME_CENTS: () => PARTNER_WELCOME_CENTS,
|
|
55
57
|
PartnerApiError: () => PartnerApiError,
|
|
56
58
|
PausedError: () => PausedError,
|
|
57
59
|
QuotaError: () => QuotaError,
|
|
@@ -62,12 +64,16 @@ __export(index_exports, {
|
|
|
62
64
|
STRICT_FIRST_DAYS: () => STRICT_FIRST_DAYS,
|
|
63
65
|
TAG_RE: () => TAG_RE,
|
|
64
66
|
TEMPLATE_VAR_NAME_RE: () => TEMPLATE_VAR_NAME_RE,
|
|
67
|
+
TENANT_DAILY_LIMIT_MAX: () => TENANT_DAILY_LIMIT_MAX,
|
|
68
|
+
TENANT_DAILY_LIMIT_START: () => TENANT_DAILY_LIMIT_START,
|
|
69
|
+
TENANT_WARMUP_STEP_DAYS: () => TENANT_WARMUP_STEP_DAYS,
|
|
65
70
|
TimeoutError: () => TimeoutError,
|
|
66
71
|
UNSUBSCRIBE_URL_VAR: () => UNSUBSCRIBE_URL_VAR,
|
|
67
72
|
ValidationError: () => ValidationError,
|
|
68
73
|
WEBHOOK_HEADERS: () => WEBHOOK_HEADERS,
|
|
69
74
|
WEBHOOK_TOLERANCE_MS: () => WEBHOOK_TOLERANCE_MS,
|
|
70
75
|
createWebhookHandler: () => createWebhookHandler,
|
|
76
|
+
estimateSendDays: () => estimateSendDays,
|
|
71
77
|
isValidExternalId: () => isValidExternalId,
|
|
72
78
|
isValidFallbackLabel: () => isValidFallbackLabel,
|
|
73
79
|
partnerSignatureBase: () => partnerSignatureBase,
|
|
@@ -80,6 +86,7 @@ __export(index_exports, {
|
|
|
80
86
|
templateVarsProblem: () => templateVarsProblem,
|
|
81
87
|
verifyWebhook: () => verifyWebhook,
|
|
82
88
|
verifyWebhookSignature: () => verifyWebhookSignature,
|
|
89
|
+
warmupLimit: () => warmupLimit,
|
|
83
90
|
webhookSignatureBase: () => webhookSignatureBase
|
|
84
91
|
});
|
|
85
92
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -724,11 +731,16 @@ var PARTNER_ERROR_STATUS = {
|
|
|
724
731
|
/** El tenant está en pausa (por MailMask o por el partner). No se manda nada hasta `resume`. */
|
|
725
732
|
tenant_paused: 423,
|
|
726
733
|
/**
|
|
727
|
-
* Saldo prepagado insuficiente (con `balanceCents` y `requiredCents`).
|
|
728
|
-
*
|
|
734
|
+
* Saldo prepagado insuficiente (con `balanceCents` y `requiredCents`). No se reintenta: recarga
|
|
735
|
+
* con `POST /topup`.
|
|
729
736
|
*/
|
|
730
737
|
insufficient_balance: 402,
|
|
731
|
-
/**
|
|
738
|
+
/**
|
|
739
|
+
* El tenant llegó a su límite del día (con `limit`, `sentToday` y `resetsAt`, la medianoche UTC).
|
|
740
|
+
* Sólo en envíos sueltos: un lote no falla, espera al día siguiente (`batch.throttled`).
|
|
741
|
+
*/
|
|
742
|
+
daily_limit: 429,
|
|
743
|
+
/** Ya no sale desde la 0.8 (no hay tope mensual); se deja para clientes viejos. */
|
|
732
744
|
quota_exceeded: 429,
|
|
733
745
|
/** Demasiadas peticiones; reintenta tras `Retry-After`. */
|
|
734
746
|
rate_limited: 429,
|
|
@@ -742,6 +754,30 @@ function isValidExternalId(id) {
|
|
|
742
754
|
var MAX_BATCH_RECIPIENTS = 1e4;
|
|
743
755
|
var MAX_TAGS = 10;
|
|
744
756
|
var TAG_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
757
|
+
var TENANT_DAILY_LIMIT_START = 2e3;
|
|
758
|
+
var TENANT_DAILY_LIMIT_MAX = 5e4;
|
|
759
|
+
var TENANT_WARMUP_STEP_DAYS = 7;
|
|
760
|
+
function warmupLimit(step) {
|
|
761
|
+
return Math.min(TENANT_DAILY_LIMIT_MAX, TENANT_DAILY_LIMIT_START * 2 ** Math.max(0, step));
|
|
762
|
+
}
|
|
763
|
+
function estimateSendDays(s, recipients) {
|
|
764
|
+
let left = recipients - Math.max(0, s.dailyLimit - s.sentToday);
|
|
765
|
+
if (left <= 0) return 1;
|
|
766
|
+
let days = 1;
|
|
767
|
+
let limit = s.dailyLimit;
|
|
768
|
+
let nextAt = s.nextStepAt ? Date.parse(s.nextStepAt) : null;
|
|
769
|
+
let day = Date.parse(s.resetsAt);
|
|
770
|
+
while (left > 0 && days < 3650) {
|
|
771
|
+
while (nextAt !== null && nextAt <= day && limit < TENANT_DAILY_LIMIT_MAX && !s.fixed) {
|
|
772
|
+
limit = Math.min(TENANT_DAILY_LIMIT_MAX, limit * 2);
|
|
773
|
+
nextAt += TENANT_WARMUP_STEP_DAYS * 864e5;
|
|
774
|
+
}
|
|
775
|
+
left -= limit;
|
|
776
|
+
days++;
|
|
777
|
+
day += 864e5;
|
|
778
|
+
}
|
|
779
|
+
return days;
|
|
780
|
+
}
|
|
745
781
|
var DOMAIN_CLAIM_TTL_DAYS = 7;
|
|
746
782
|
var FALLBACK_LABEL_RE = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
747
783
|
var RESERVED_FALLBACK_LABELS = [
|
|
@@ -809,6 +845,7 @@ function personalizePartnerMessage(input) {
|
|
|
809
845
|
}
|
|
810
846
|
var PARTNER_PRICE_PER_EMAIL_CENTS = 6;
|
|
811
847
|
var PARTNER_TENANT_MONTH_CENTS = 4900;
|
|
848
|
+
var PARTNER_WELCOME_CENTS = 5e4;
|
|
812
849
|
var PARTNER_TOPUP_MIN_CENTS = 5e4;
|
|
813
850
|
var PARTNER_TOPUP_MAX_CENTS = 1e7;
|
|
814
851
|
var BALANCE_LOW_FRACTION = 0.2;
|
|
@@ -823,7 +860,8 @@ var PARTNER_WEBHOOK_EVENTS = [
|
|
|
823
860
|
"tenant.paused",
|
|
824
861
|
"tenant.resumed",
|
|
825
862
|
"domain.verified",
|
|
826
|
-
"balance.low"
|
|
863
|
+
"balance.low",
|
|
864
|
+
"batch.throttled"
|
|
827
865
|
];
|
|
828
866
|
var WEBHOOK_HEADERS = {
|
|
829
867
|
event: "X-MailMask-Event",
|
|
@@ -877,10 +915,10 @@ var PARTNER_ADMIN_ROUTES = {
|
|
|
877
915
|
getBalance: { method: "GET", path: "/api/partners/:partnerId/balance" },
|
|
878
916
|
/** Sólo MailMask (admin): abono o cargo manual (`adjust`). */
|
|
879
917
|
adjustBalance: { method: "POST", path: "/api/partners/:partnerId/balance/adjust" },
|
|
880
|
-
/** Sólo MailMask (admin): prende o apaga el cobro por adelantado. */
|
|
881
|
-
setPrepaidEnforced: { method: "PUT", path: "/api/partners/:partnerId/prepaid" },
|
|
882
918
|
/** Recarga con MercadoPago desde la sesión del dueño (misma respuesta que `POST /topup`). */
|
|
883
919
|
topup: { method: "POST", path: "/api/partners/:partnerId/topup" },
|
|
920
|
+
/** Sólo MailMask: fija (o quita, con `null`) el límite diario de un tenant. Devuelve el `Tenant`. */
|
|
921
|
+
setTenantDailyLimit: { method: "PUT", path: "/api/partners/:partnerId/tenants/:externalId/daily-limit" },
|
|
884
922
|
listCredentials: { method: "GET", path: "/api/partners/:partnerId/credentials" },
|
|
885
923
|
createCredential: { method: "POST", path: "/api/partners/:partnerId/credentials" },
|
|
886
924
|
rotateCredential: { method: "POST", path: "/api/partners/:partnerId/credentials/:keyId/rotate" },
|
|
@@ -894,8 +932,8 @@ var PartnerApiError = class extends MailMaskError {
|
|
|
894
932
|
code: body.code,
|
|
895
933
|
requestId: meta.requestId,
|
|
896
934
|
cause: meta.cause,
|
|
897
|
-
// `quota_exceeded`
|
|
898
|
-
retryable: status === 0 || status >= 500 || status === 429 && body.code !== "quota_exceeded"
|
|
935
|
+
// `daily_limit` (y el viejo `quota_exceeded`) son 429 que no se arreglan reintentando: hasta mañana.
|
|
936
|
+
retryable: status === 0 || status >= 500 || status === 429 && body.code !== "quota_exceeded" && body.code !== "daily_limit"
|
|
899
937
|
});
|
|
900
938
|
this.kind = "unknown";
|
|
901
939
|
this.name = "PartnerApiError";
|
|
@@ -998,6 +1036,16 @@ var RateLimitError = class extends QuotaError {
|
|
|
998
1036
|
this.kind = "rate_limit";
|
|
999
1037
|
}
|
|
1000
1038
|
};
|
|
1039
|
+
var DailyLimitError = class extends QuotaError {
|
|
1040
|
+
constructor() {
|
|
1041
|
+
super(...arguments);
|
|
1042
|
+
this.name = "DailyLimitError";
|
|
1043
|
+
this.kind = "daily_limit";
|
|
1044
|
+
}
|
|
1045
|
+
get sentToday() {
|
|
1046
|
+
return this.body.sentToday;
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1001
1049
|
var InsufficientBalanceError = class extends PartnerApiError {
|
|
1002
1050
|
constructor() {
|
|
1003
1051
|
super(...arguments);
|
|
@@ -1029,6 +1077,7 @@ function errorFor(status, body, fallback, meta = {}) {
|
|
|
1029
1077
|
const msg = body.error || fallback;
|
|
1030
1078
|
if (body.code === "reputation_hold") return new ReputationHoldError(status, msg, body, meta);
|
|
1031
1079
|
if (body.code === "recipient_suppressed") return new RecipientSuppressedError(status, msg, body, meta);
|
|
1080
|
+
if (status === 429 && body.code === "daily_limit") return new DailyLimitError(status, msg, body, meta);
|
|
1032
1081
|
if (status === 429 && body.code !== "quota_exceeded") return new RateLimitError(status, msg, body, meta);
|
|
1033
1082
|
switch (status) {
|
|
1034
1083
|
case 401:
|
|
@@ -1459,6 +1508,10 @@ var MailMaskPartnerAdmin = class {
|
|
|
1459
1508
|
resumeTenant(partnerId, externalId) {
|
|
1460
1509
|
return this.req("resumeTenant", { partnerId, externalId });
|
|
1461
1510
|
}
|
|
1511
|
+
/** Sólo MailMask: tope diario fijo del tenant, o `null` para volver al calentamiento. */
|
|
1512
|
+
setTenantDailyLimit(partnerId, externalId, limit) {
|
|
1513
|
+
return this.req("setTenantDailyLimit", { partnerId, externalId }, { limit });
|
|
1514
|
+
}
|
|
1462
1515
|
/**
|
|
1463
1516
|
* Sólo MailMask (admin): crea o adopta la hosted zone de la zona de respaldo (`marketing.denik.me`)
|
|
1464
1517
|
* y devuelve los NS que el partner tiene que delegar. Idempotente con la misma zona.
|
|
@@ -1478,10 +1531,6 @@ var MailMaskPartnerAdmin = class {
|
|
|
1478
1531
|
adjustBalance(partnerId, input) {
|
|
1479
1532
|
return this.req("adjustBalance", { partnerId }, input);
|
|
1480
1533
|
}
|
|
1481
|
-
/** Sólo MailMask (admin): prende o apaga el cobro por adelantado del partner. */
|
|
1482
|
-
setPrepaidEnforced(partnerId, enforced) {
|
|
1483
|
-
return this.req("setPrepaidEnforced", { partnerId }, { enforced });
|
|
1484
|
-
}
|
|
1485
1534
|
/** Liga de MercadoPago para recargar, con la llave del dueño. */
|
|
1486
1535
|
topup(partnerId, input) {
|
|
1487
1536
|
return this.req("topup", { partnerId }, input);
|
|
@@ -1509,6 +1558,7 @@ var MailMaskPartnerAdmin = class {
|
|
|
1509
1558
|
BALANCE_MOVEMENT_KINDS,
|
|
1510
1559
|
ConflictError,
|
|
1511
1560
|
DOMAIN_CLAIM_TTL_DAYS,
|
|
1561
|
+
DailyLimitError,
|
|
1512
1562
|
EXTERNAL_ID_RE,
|
|
1513
1563
|
FALLBACK_LABEL_RE,
|
|
1514
1564
|
ForbiddenError,
|
|
@@ -1536,6 +1586,7 @@ var MailMaskPartnerAdmin = class {
|
|
|
1536
1586
|
PARTNER_TOPUP_MAX_CENTS,
|
|
1537
1587
|
PARTNER_TOPUP_MIN_CENTS,
|
|
1538
1588
|
PARTNER_WEBHOOK_EVENTS,
|
|
1589
|
+
PARTNER_WELCOME_CENTS,
|
|
1539
1590
|
PartnerApiError,
|
|
1540
1591
|
PausedError,
|
|
1541
1592
|
QuotaError,
|
|
@@ -1546,12 +1597,16 @@ var MailMaskPartnerAdmin = class {
|
|
|
1546
1597
|
STRICT_FIRST_DAYS,
|
|
1547
1598
|
TAG_RE,
|
|
1548
1599
|
TEMPLATE_VAR_NAME_RE,
|
|
1600
|
+
TENANT_DAILY_LIMIT_MAX,
|
|
1601
|
+
TENANT_DAILY_LIMIT_START,
|
|
1602
|
+
TENANT_WARMUP_STEP_DAYS,
|
|
1549
1603
|
TimeoutError,
|
|
1550
1604
|
UNSUBSCRIBE_URL_VAR,
|
|
1551
1605
|
ValidationError,
|
|
1552
1606
|
WEBHOOK_HEADERS,
|
|
1553
1607
|
WEBHOOK_TOLERANCE_MS,
|
|
1554
1608
|
createWebhookHandler,
|
|
1609
|
+
estimateSendDays,
|
|
1555
1610
|
isValidExternalId,
|
|
1556
1611
|
isValidFallbackLabel,
|
|
1557
1612
|
partnerSignatureBase,
|
|
@@ -1564,5 +1619,6 @@ var MailMaskPartnerAdmin = class {
|
|
|
1564
1619
|
templateVarsProblem,
|
|
1565
1620
|
verifyWebhook,
|
|
1566
1621
|
verifyWebhookSignature,
|
|
1622
|
+
warmupLimit,
|
|
1567
1623
|
webhookSignatureBase
|
|
1568
1624
|
});
|
package/dist/index.js
CHANGED
|
@@ -638,11 +638,16 @@ var PARTNER_ERROR_STATUS = {
|
|
|
638
638
|
/** El tenant está en pausa (por MailMask o por el partner). No se manda nada hasta `resume`. */
|
|
639
639
|
tenant_paused: 423,
|
|
640
640
|
/**
|
|
641
|
-
* Saldo prepagado insuficiente (con `balanceCents` y `requiredCents`).
|
|
642
|
-
*
|
|
641
|
+
* Saldo prepagado insuficiente (con `balanceCents` y `requiredCents`). No se reintenta: recarga
|
|
642
|
+
* con `POST /topup`.
|
|
643
643
|
*/
|
|
644
644
|
insufficient_balance: 402,
|
|
645
|
-
/**
|
|
645
|
+
/**
|
|
646
|
+
* El tenant llegó a su límite del día (con `limit`, `sentToday` y `resetsAt`, la medianoche UTC).
|
|
647
|
+
* Sólo en envíos sueltos: un lote no falla, espera al día siguiente (`batch.throttled`).
|
|
648
|
+
*/
|
|
649
|
+
daily_limit: 429,
|
|
650
|
+
/** Ya no sale desde la 0.8 (no hay tope mensual); se deja para clientes viejos. */
|
|
646
651
|
quota_exceeded: 429,
|
|
647
652
|
/** Demasiadas peticiones; reintenta tras `Retry-After`. */
|
|
648
653
|
rate_limited: 429,
|
|
@@ -656,6 +661,30 @@ function isValidExternalId(id) {
|
|
|
656
661
|
var MAX_BATCH_RECIPIENTS = 1e4;
|
|
657
662
|
var MAX_TAGS = 10;
|
|
658
663
|
var TAG_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
664
|
+
var TENANT_DAILY_LIMIT_START = 2e3;
|
|
665
|
+
var TENANT_DAILY_LIMIT_MAX = 5e4;
|
|
666
|
+
var TENANT_WARMUP_STEP_DAYS = 7;
|
|
667
|
+
function warmupLimit(step) {
|
|
668
|
+
return Math.min(TENANT_DAILY_LIMIT_MAX, TENANT_DAILY_LIMIT_START * 2 ** Math.max(0, step));
|
|
669
|
+
}
|
|
670
|
+
function estimateSendDays(s, recipients) {
|
|
671
|
+
let left = recipients - Math.max(0, s.dailyLimit - s.sentToday);
|
|
672
|
+
if (left <= 0) return 1;
|
|
673
|
+
let days = 1;
|
|
674
|
+
let limit = s.dailyLimit;
|
|
675
|
+
let nextAt = s.nextStepAt ? Date.parse(s.nextStepAt) : null;
|
|
676
|
+
let day = Date.parse(s.resetsAt);
|
|
677
|
+
while (left > 0 && days < 3650) {
|
|
678
|
+
while (nextAt !== null && nextAt <= day && limit < TENANT_DAILY_LIMIT_MAX && !s.fixed) {
|
|
679
|
+
limit = Math.min(TENANT_DAILY_LIMIT_MAX, limit * 2);
|
|
680
|
+
nextAt += TENANT_WARMUP_STEP_DAYS * 864e5;
|
|
681
|
+
}
|
|
682
|
+
left -= limit;
|
|
683
|
+
days++;
|
|
684
|
+
day += 864e5;
|
|
685
|
+
}
|
|
686
|
+
return days;
|
|
687
|
+
}
|
|
659
688
|
var DOMAIN_CLAIM_TTL_DAYS = 7;
|
|
660
689
|
var FALLBACK_LABEL_RE = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
661
690
|
var RESERVED_FALLBACK_LABELS = [
|
|
@@ -723,6 +752,7 @@ function personalizePartnerMessage(input) {
|
|
|
723
752
|
}
|
|
724
753
|
var PARTNER_PRICE_PER_EMAIL_CENTS = 6;
|
|
725
754
|
var PARTNER_TENANT_MONTH_CENTS = 4900;
|
|
755
|
+
var PARTNER_WELCOME_CENTS = 5e4;
|
|
726
756
|
var PARTNER_TOPUP_MIN_CENTS = 5e4;
|
|
727
757
|
var PARTNER_TOPUP_MAX_CENTS = 1e7;
|
|
728
758
|
var BALANCE_LOW_FRACTION = 0.2;
|
|
@@ -737,7 +767,8 @@ var PARTNER_WEBHOOK_EVENTS = [
|
|
|
737
767
|
"tenant.paused",
|
|
738
768
|
"tenant.resumed",
|
|
739
769
|
"domain.verified",
|
|
740
|
-
"balance.low"
|
|
770
|
+
"balance.low",
|
|
771
|
+
"batch.throttled"
|
|
741
772
|
];
|
|
742
773
|
var WEBHOOK_HEADERS = {
|
|
743
774
|
event: "X-MailMask-Event",
|
|
@@ -791,10 +822,10 @@ var PARTNER_ADMIN_ROUTES = {
|
|
|
791
822
|
getBalance: { method: "GET", path: "/api/partners/:partnerId/balance" },
|
|
792
823
|
/** Sólo MailMask (admin): abono o cargo manual (`adjust`). */
|
|
793
824
|
adjustBalance: { method: "POST", path: "/api/partners/:partnerId/balance/adjust" },
|
|
794
|
-
/** Sólo MailMask (admin): prende o apaga el cobro por adelantado. */
|
|
795
|
-
setPrepaidEnforced: { method: "PUT", path: "/api/partners/:partnerId/prepaid" },
|
|
796
825
|
/** Recarga con MercadoPago desde la sesión del dueño (misma respuesta que `POST /topup`). */
|
|
797
826
|
topup: { method: "POST", path: "/api/partners/:partnerId/topup" },
|
|
827
|
+
/** Sólo MailMask: fija (o quita, con `null`) el límite diario de un tenant. Devuelve el `Tenant`. */
|
|
828
|
+
setTenantDailyLimit: { method: "PUT", path: "/api/partners/:partnerId/tenants/:externalId/daily-limit" },
|
|
798
829
|
listCredentials: { method: "GET", path: "/api/partners/:partnerId/credentials" },
|
|
799
830
|
createCredential: { method: "POST", path: "/api/partners/:partnerId/credentials" },
|
|
800
831
|
rotateCredential: { method: "POST", path: "/api/partners/:partnerId/credentials/:keyId/rotate" },
|
|
@@ -808,8 +839,8 @@ var PartnerApiError = class extends MailMaskError {
|
|
|
808
839
|
code: body.code,
|
|
809
840
|
requestId: meta.requestId,
|
|
810
841
|
cause: meta.cause,
|
|
811
|
-
// `quota_exceeded`
|
|
812
|
-
retryable: status === 0 || status >= 500 || status === 429 && body.code !== "quota_exceeded"
|
|
842
|
+
// `daily_limit` (y el viejo `quota_exceeded`) son 429 que no se arreglan reintentando: hasta mañana.
|
|
843
|
+
retryable: status === 0 || status >= 500 || status === 429 && body.code !== "quota_exceeded" && body.code !== "daily_limit"
|
|
813
844
|
});
|
|
814
845
|
this.kind = "unknown";
|
|
815
846
|
this.name = "PartnerApiError";
|
|
@@ -912,6 +943,16 @@ var RateLimitError = class extends QuotaError {
|
|
|
912
943
|
this.kind = "rate_limit";
|
|
913
944
|
}
|
|
914
945
|
};
|
|
946
|
+
var DailyLimitError = class extends QuotaError {
|
|
947
|
+
constructor() {
|
|
948
|
+
super(...arguments);
|
|
949
|
+
this.name = "DailyLimitError";
|
|
950
|
+
this.kind = "daily_limit";
|
|
951
|
+
}
|
|
952
|
+
get sentToday() {
|
|
953
|
+
return this.body.sentToday;
|
|
954
|
+
}
|
|
955
|
+
};
|
|
915
956
|
var InsufficientBalanceError = class extends PartnerApiError {
|
|
916
957
|
constructor() {
|
|
917
958
|
super(...arguments);
|
|
@@ -943,6 +984,7 @@ function errorFor(status, body, fallback, meta = {}) {
|
|
|
943
984
|
const msg = body.error || fallback;
|
|
944
985
|
if (body.code === "reputation_hold") return new ReputationHoldError(status, msg, body, meta);
|
|
945
986
|
if (body.code === "recipient_suppressed") return new RecipientSuppressedError(status, msg, body, meta);
|
|
987
|
+
if (status === 429 && body.code === "daily_limit") return new DailyLimitError(status, msg, body, meta);
|
|
946
988
|
if (status === 429 && body.code !== "quota_exceeded") return new RateLimitError(status, msg, body, meta);
|
|
947
989
|
switch (status) {
|
|
948
990
|
case 401:
|
|
@@ -1373,6 +1415,10 @@ var MailMaskPartnerAdmin = class {
|
|
|
1373
1415
|
resumeTenant(partnerId, externalId) {
|
|
1374
1416
|
return this.req("resumeTenant", { partnerId, externalId });
|
|
1375
1417
|
}
|
|
1418
|
+
/** Sólo MailMask: tope diario fijo del tenant, o `null` para volver al calentamiento. */
|
|
1419
|
+
setTenantDailyLimit(partnerId, externalId, limit) {
|
|
1420
|
+
return this.req("setTenantDailyLimit", { partnerId, externalId }, { limit });
|
|
1421
|
+
}
|
|
1376
1422
|
/**
|
|
1377
1423
|
* Sólo MailMask (admin): crea o adopta la hosted zone de la zona de respaldo (`marketing.denik.me`)
|
|
1378
1424
|
* y devuelve los NS que el partner tiene que delegar. Idempotente con la misma zona.
|
|
@@ -1392,10 +1438,6 @@ var MailMaskPartnerAdmin = class {
|
|
|
1392
1438
|
adjustBalance(partnerId, input) {
|
|
1393
1439
|
return this.req("adjustBalance", { partnerId }, input);
|
|
1394
1440
|
}
|
|
1395
|
-
/** Sólo MailMask (admin): prende o apaga el cobro por adelantado del partner. */
|
|
1396
|
-
setPrepaidEnforced(partnerId, enforced) {
|
|
1397
|
-
return this.req("setPrepaidEnforced", { partnerId }, { enforced });
|
|
1398
|
-
}
|
|
1399
1441
|
/** Liga de MercadoPago para recargar, con la llave del dueño. */
|
|
1400
1442
|
topup(partnerId, input) {
|
|
1401
1443
|
return this.req("topup", { partnerId }, input);
|
|
@@ -1422,6 +1464,7 @@ export {
|
|
|
1422
1464
|
BALANCE_MOVEMENT_KINDS,
|
|
1423
1465
|
ConflictError,
|
|
1424
1466
|
DOMAIN_CLAIM_TTL_DAYS,
|
|
1467
|
+
DailyLimitError,
|
|
1425
1468
|
EXTERNAL_ID_RE,
|
|
1426
1469
|
FALLBACK_LABEL_RE,
|
|
1427
1470
|
ForbiddenError,
|
|
@@ -1449,6 +1492,7 @@ export {
|
|
|
1449
1492
|
PARTNER_TOPUP_MAX_CENTS,
|
|
1450
1493
|
PARTNER_TOPUP_MIN_CENTS,
|
|
1451
1494
|
PARTNER_WEBHOOK_EVENTS,
|
|
1495
|
+
PARTNER_WELCOME_CENTS,
|
|
1452
1496
|
PartnerApiError,
|
|
1453
1497
|
PausedError,
|
|
1454
1498
|
QuotaError,
|
|
@@ -1459,12 +1503,16 @@ export {
|
|
|
1459
1503
|
STRICT_FIRST_DAYS,
|
|
1460
1504
|
TAG_RE,
|
|
1461
1505
|
TEMPLATE_VAR_NAME_RE,
|
|
1506
|
+
TENANT_DAILY_LIMIT_MAX,
|
|
1507
|
+
TENANT_DAILY_LIMIT_START,
|
|
1508
|
+
TENANT_WARMUP_STEP_DAYS,
|
|
1462
1509
|
TimeoutError,
|
|
1463
1510
|
UNSUBSCRIBE_URL_VAR,
|
|
1464
1511
|
ValidationError,
|
|
1465
1512
|
WEBHOOK_HEADERS,
|
|
1466
1513
|
WEBHOOK_TOLERANCE_MS,
|
|
1467
1514
|
createWebhookHandler,
|
|
1515
|
+
estimateSendDays,
|
|
1468
1516
|
isValidExternalId,
|
|
1469
1517
|
isValidFallbackLabel,
|
|
1470
1518
|
partnerSignatureBase,
|
|
@@ -1477,5 +1525,6 @@ export {
|
|
|
1477
1525
|
templateVarsProblem,
|
|
1478
1526
|
verifyWebhook,
|
|
1479
1527
|
verifyWebhookSignature,
|
|
1528
|
+
warmupLimit,
|
|
1480
1529
|
webhookSignatureBase
|
|
1481
1530
|
};
|
|
@@ -60,11 +60,16 @@ export declare const PARTNER_ERROR_STATUS: {
|
|
|
60
60
|
/** El tenant está en pausa (por MailMask o por el partner). No se manda nada hasta `resume`. */
|
|
61
61
|
readonly tenant_paused: 423;
|
|
62
62
|
/**
|
|
63
|
-
* Saldo prepagado insuficiente (con `balanceCents` y `requiredCents`).
|
|
64
|
-
*
|
|
63
|
+
* Saldo prepagado insuficiente (con `balanceCents` y `requiredCents`). No se reintenta: recarga
|
|
64
|
+
* con `POST /topup`.
|
|
65
65
|
*/
|
|
66
66
|
readonly insufficient_balance: 402;
|
|
67
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* El tenant llegó a su límite del día (con `limit`, `sentToday` y `resetsAt`, la medianoche UTC).
|
|
69
|
+
* Sólo en envíos sueltos: un lote no falla, espera al día siguiente (`batch.throttled`).
|
|
70
|
+
*/
|
|
71
|
+
readonly daily_limit: 429;
|
|
72
|
+
/** Ya no sale desde la 0.8 (no hay tope mensual); se deja para clientes viejos. */
|
|
68
73
|
readonly quota_exceeded: 429;
|
|
69
74
|
/** Demasiadas peticiones; reintenta tras `Retry-After`. */
|
|
70
75
|
readonly rate_limited: 429;
|
|
@@ -77,8 +82,9 @@ export interface PartnerErrorBody {
|
|
|
77
82
|
code: PartnerErrorCode;
|
|
78
83
|
/** Sólo en `invalid_request`: el campo que falló, si aplica. */
|
|
79
84
|
field?: string;
|
|
80
|
-
/** Sólo en `
|
|
85
|
+
/** Sólo en `daily_limit`: el límite de hoy, lo enviado y cuándo se reinicia (medianoche UTC). */
|
|
81
86
|
limit?: number;
|
|
87
|
+
sentToday?: number;
|
|
82
88
|
resetsAt?: string;
|
|
83
89
|
/** Sólo en `insufficient_balance`: saldo actual y lo que pedía el envío (centavos MXN). */
|
|
84
90
|
balanceCents?: number;
|
|
@@ -112,7 +118,38 @@ export interface Tenant {
|
|
|
112
118
|
lastSendAt: string | null;
|
|
113
119
|
createdAt: string;
|
|
114
120
|
updatedAt: string;
|
|
121
|
+
/** Límite diario con calentamiento. Ver `TenantSending`. */
|
|
122
|
+
sending: TenantSending;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Límite diario por tenant que crece solo, como el calentamiento de SES: empieza en
|
|
126
|
+
* `TENANT_DAILY_LIMIT_START` al primer envío y se duplica cada `TENANT_WARMUP_STEP_DAYS` días sanos
|
|
127
|
+
* (rebotes < 2 %, quejas < 0.1 %) hasta `TENANT_DAILY_LIMIT_MAX`. Una pausa por reputación lo
|
|
128
|
+
* regresa al inicio al reanudar. No hay tope mensual: el saldo es el otro freno.
|
|
129
|
+
*/
|
|
130
|
+
export declare const TENANT_DAILY_LIMIT_START = 2000;
|
|
131
|
+
export declare const TENANT_DAILY_LIMIT_MAX = 50000;
|
|
132
|
+
export declare const TENANT_WARMUP_STEP_DAYS = 7;
|
|
133
|
+
/** El límite del escalón `step` (0 = inicio). */
|
|
134
|
+
export declare function warmupLimit(step: number): number;
|
|
135
|
+
export interface TenantSending {
|
|
136
|
+
/** Correos que puede mandar hoy (UTC) en total. */
|
|
137
|
+
dailyLimit: number;
|
|
138
|
+
sentToday: number;
|
|
139
|
+
/** Medianoche UTC siguiente. */
|
|
140
|
+
resetsAt: string;
|
|
141
|
+
/** Cuándo sube al siguiente escalón si sigue sano; null = ya en el máximo, con tope fijo o sin envíos aún. */
|
|
142
|
+
nextStepAt: string | null;
|
|
143
|
+
/** El límite que tendrá en `nextStepAt`; null si no sube. */
|
|
144
|
+
nextStepLimit: number | null;
|
|
145
|
+
/** true = MailMask fijó el límite a mano (no se calienta). */
|
|
146
|
+
fixed: boolean;
|
|
115
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Días (contando hoy) que tarda en salir un lote de `recipients` correos si los escalones llegan a
|
|
150
|
+
* tiempo. 1 = sale hoy. Sirve para avisar «se manda en N días» antes de encolar.
|
|
151
|
+
*/
|
|
152
|
+
export declare function estimateSendDays(s: TenantSending, recipients: number): number;
|
|
116
153
|
/** `PUT /tenants/:externalId` — crea o actualiza. 201 si lo creó, 200 si ya existía. */
|
|
117
154
|
export interface PutTenantRequest {
|
|
118
155
|
name?: string;
|
|
@@ -351,6 +388,11 @@ export interface BatchStatus {
|
|
|
351
388
|
lastError: string | null;
|
|
352
389
|
createdAt: string;
|
|
353
390
|
completedAt: string | null;
|
|
391
|
+
/**
|
|
392
|
+
* El lote llegó al límite diario del tenant y sigue solo a esta hora (medianoche UTC); null si no
|
|
393
|
+
* está esperando por el límite. Mientras espera, el lote no caduca.
|
|
394
|
+
*/
|
|
395
|
+
waitingUntil: string | null;
|
|
354
396
|
/**
|
|
355
397
|
* Sólo en modo de prueba: el lote se valida y responde `completed` al instante (los suprimidos en
|
|
356
398
|
* `skippedSuppressed`, el resto en `sent`), con `batchId` `test_…` que no se guarda (su GET da 404).
|
|
@@ -368,6 +410,8 @@ export interface TenantUsage {
|
|
|
368
410
|
bounced: number;
|
|
369
411
|
complained: number;
|
|
370
412
|
unsubscribed: number;
|
|
413
|
+
/** Límite diario de hoy; falta si el tenant ya se borró. */
|
|
414
|
+
sending?: TenantSending;
|
|
371
415
|
}
|
|
372
416
|
/** `GET /usage?month=YYYY-MM` (default: el mes en curso, UTC). Activo = al menos un envío en el mes. */
|
|
373
417
|
export interface UsageResponse {
|
|
@@ -387,6 +431,8 @@ export declare const PARTNER_PRICE_PER_EMAIL_CENTS = 6;
|
|
|
387
431
|
* mes (UTC), una sola vez, así que un tenant dormido no cuesta nada.
|
|
388
432
|
*/
|
|
389
433
|
export declare const PARTNER_TENANT_MONTH_CENTS = 4900;
|
|
434
|
+
/** Saldo de bienvenida con el que nace todo partner (`adjust`, idemKey `welcome:<partnerId>`). */
|
|
435
|
+
export declare const PARTNER_WELCOME_CENTS = 50000;
|
|
390
436
|
/** Recarga mínima y máxima por pago. */
|
|
391
437
|
export declare const PARTNER_TOPUP_MIN_CENTS = 50000;
|
|
392
438
|
export declare const PARTNER_TOPUP_MAX_CENTS = 10000000;
|
|
@@ -410,12 +456,8 @@ export interface BalanceMovement {
|
|
|
410
456
|
/** `GET /balance` */
|
|
411
457
|
export interface BalanceResponse {
|
|
412
458
|
currency: "MXN";
|
|
459
|
+
/** Sin saldo suficiente el envío se rechaza (402 `insufficient_balance`) y el lote espera. Siempre. */
|
|
413
460
|
balanceCents: number;
|
|
414
|
-
/**
|
|
415
|
-
* true = sin saldo suficiente los envíos se rechazan (402 `insufficient_balance`) y los lotes
|
|
416
|
-
* esperan. false = el saldo se lleva igual (puede quedar negativo) pero no frena nada.
|
|
417
|
-
*/
|
|
418
|
-
enforced: boolean;
|
|
419
461
|
prices: {
|
|
420
462
|
perEmailCents: number;
|
|
421
463
|
tenantMonthCents: number;
|
|
@@ -429,7 +471,7 @@ export interface BalanceResponse {
|
|
|
429
471
|
lowBalanceThresholdCents: number | null;
|
|
430
472
|
/** Mes en curso (UTC). */
|
|
431
473
|
month: string;
|
|
432
|
-
/** Tenants
|
|
474
|
+
/** Tenants que enviaron este mes (la misma cuenta que `/usage`): cada uno paga la cuota del mes. */
|
|
433
475
|
activeTenants: number;
|
|
434
476
|
/** Correos cobrados en el mes (sin los devueltos). */
|
|
435
477
|
monthEmails: number;
|
|
@@ -466,11 +508,24 @@ export interface TopupResponse {
|
|
|
466
508
|
* `GET /api/partners/:partnerId/balance` (dueño o MailMask): el saldo, sus últimos 20 movimientos,
|
|
467
509
|
* el partner (con `tenants` y `ownerEmail`) y si quien mira es de MailMask (ve abonar y el cobro).
|
|
468
510
|
*/
|
|
511
|
+
/** Un tenant en la ficha: los 50 que enviaron más recientemente, con su límite de hoy. */
|
|
512
|
+
export interface PartnerDetailTenant {
|
|
513
|
+
externalId: string;
|
|
514
|
+
name: string | null;
|
|
515
|
+
status: TenantStatus;
|
|
516
|
+
lastSendAt: string | null;
|
|
517
|
+
sending: TenantSending;
|
|
518
|
+
}
|
|
469
519
|
export type PartnerBalanceDetail = BalanceResponse & {
|
|
470
520
|
movements: BalanceMovement[];
|
|
471
521
|
partner: PartnerSummary;
|
|
522
|
+
tenants: PartnerDetailTenant[];
|
|
472
523
|
staff: boolean;
|
|
473
524
|
};
|
|
525
|
+
/** `PUT /api/partners/:partnerId/tenants/:externalId/daily-limit` — sólo MailMask: tope fijo o `null` (vuelve al calentamiento). */
|
|
526
|
+
export interface SetTenantDailyLimitRequest {
|
|
527
|
+
limit: number | null;
|
|
528
|
+
}
|
|
474
529
|
/** `POST /api/partners/:partnerId/balance/adjust` — sólo MailMask (admin): abono o cargo manual. */
|
|
475
530
|
export interface AdjustBalanceRequest {
|
|
476
531
|
/** Centavos MXN, distinto de 0 (negativo = cargo). */
|
|
@@ -479,10 +534,6 @@ export interface AdjustBalanceRequest {
|
|
|
479
534
|
/** Repetir con la misma llave no vuelve a abonar. */
|
|
480
535
|
idempotencyKey?: string;
|
|
481
536
|
}
|
|
482
|
-
/** `PUT /api/partners/:partnerId/prepaid` — sólo MailMask (admin): prende o apaga el cobro por adelantado. */
|
|
483
|
-
export interface SetPrepaidEnforcedRequest {
|
|
484
|
-
enforced: boolean;
|
|
485
|
-
}
|
|
486
537
|
/** `GET /webhook` */
|
|
487
538
|
export interface WebhookConfig {
|
|
488
539
|
url: string | null;
|
|
@@ -516,7 +567,7 @@ export interface RotateWebhookSecretResponse {
|
|
|
516
567
|
export interface TestWebhookResponse {
|
|
517
568
|
deliveryId: string;
|
|
518
569
|
}
|
|
519
|
-
export declare const PARTNER_WEBHOOK_EVENTS: readonly ["email.sent", "email.delivered", "email.bounced", "email.complained", "email.received", "contact.unsubscribed", "tenant.paused", "tenant.resumed", "domain.verified", "balance.low"];
|
|
570
|
+
export declare const PARTNER_WEBHOOK_EVENTS: readonly ["email.sent", "email.delivered", "email.bounced", "email.complained", "email.received", "contact.unsubscribed", "tenant.paused", "tenant.resumed", "domain.verified", "balance.low", "batch.throttled"];
|
|
520
571
|
export type PartnerWebhookEvent = typeof PARTNER_WEBHOOK_EVENTS[number];
|
|
521
572
|
/** Headers de cada entrega al webhook del partner (los mismos que los webhooks de dominio). */
|
|
522
573
|
export declare const WEBHOOK_HEADERS: {
|
|
@@ -600,6 +651,14 @@ export interface PartnerEventData {
|
|
|
600
651
|
thresholdCents: number;
|
|
601
652
|
lastTopupCents: number;
|
|
602
653
|
};
|
|
654
|
+
/** Un lote llegó al límite diario del tenant: sigue solo en `resumesAt`. Una vez por lote. */
|
|
655
|
+
"batch.throttled": {
|
|
656
|
+
batchId: string;
|
|
657
|
+
sent: number;
|
|
658
|
+
total: number;
|
|
659
|
+
dailyLimit: number;
|
|
660
|
+
resumesAt: string;
|
|
661
|
+
};
|
|
603
662
|
ping: Record<string, never>;
|
|
604
663
|
}
|
|
605
664
|
/** Sobre de cada evento. `externalId` es null en `ping` y `balance.low`. */
|
|
@@ -623,6 +682,7 @@ export declare const STRICT_FIRST_DAYS = 30;
|
|
|
623
682
|
export interface PartnerSummary {
|
|
624
683
|
id: string;
|
|
625
684
|
name: string;
|
|
685
|
+
/** `sendsPerTenantMonth` ya no frena (0.8): el límite es diario por tenant, ver `TenantSending`. */
|
|
626
686
|
plan: {
|
|
627
687
|
includedTenants: number;
|
|
628
688
|
sendsPerTenantMonth: number;
|
|
@@ -636,9 +696,8 @@ export interface PartnerSummary {
|
|
|
636
696
|
effectiveReputationPolicy: ReputationPolicy;
|
|
637
697
|
/** Zona de respaldo (`marketing.denik.me`); null = sin zona. Ver `FallbackZone`. */
|
|
638
698
|
fallbackZone: string | null;
|
|
639
|
-
/** Saldo prepagado (centavos MXN)
|
|
699
|
+
/** Saldo prepagado (centavos MXN). Ver `BalanceResponse`. */
|
|
640
700
|
balanceCents: number;
|
|
641
|
-
prepaidEnforced: boolean;
|
|
642
701
|
/** Sólo en `GET /api/partners?all=1` (MailMask, admin): tenants totales y activos del mes. */
|
|
643
702
|
tenants?: {
|
|
644
703
|
total: number;
|
|
@@ -829,16 +888,16 @@ export declare const PARTNER_ADMIN_ROUTES: {
|
|
|
829
888
|
readonly method: "POST";
|
|
830
889
|
readonly path: "/api/partners/:partnerId/balance/adjust";
|
|
831
890
|
};
|
|
832
|
-
/** Sólo MailMask (admin): prende o apaga el cobro por adelantado. */
|
|
833
|
-
readonly setPrepaidEnforced: {
|
|
834
|
-
readonly method: "PUT";
|
|
835
|
-
readonly path: "/api/partners/:partnerId/prepaid";
|
|
836
|
-
};
|
|
837
891
|
/** Recarga con MercadoPago desde la sesión del dueño (misma respuesta que `POST /topup`). */
|
|
838
892
|
readonly topup: {
|
|
839
893
|
readonly method: "POST";
|
|
840
894
|
readonly path: "/api/partners/:partnerId/topup";
|
|
841
895
|
};
|
|
896
|
+
/** Sólo MailMask: fija (o quita, con `null`) el límite diario de un tenant. Devuelve el `Tenant`. */
|
|
897
|
+
readonly setTenantDailyLimit: {
|
|
898
|
+
readonly method: "PUT";
|
|
899
|
+
readonly path: "/api/partners/:partnerId/tenants/:externalId/daily-limit";
|
|
900
|
+
};
|
|
842
901
|
readonly listCredentials: {
|
|
843
902
|
readonly method: "GET";
|
|
844
903
|
readonly path: "/api/partners/:partnerId/credentials";
|
package/dist/partner.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export * from "./partner-contract.js";
|
|
|
6
6
|
* `network` y `timeout` llevan `status` 0 (no hubo respuesta); `unknown` es un status que el
|
|
7
7
|
* contrato no define (p. ej. un 400 de un proxy).
|
|
8
8
|
*/
|
|
9
|
-
export type PartnerErrorKind = "auth" | "forbidden" | "reputation_hold" | "not_found" | "conflict" | "validation" | "suppressed" | "paused" | "quota" | "insufficient_balance" | "rate_limit" | "server" | "network" | "timeout" | "unknown";
|
|
9
|
+
export type PartnerErrorKind = "auth" | "forbidden" | "reputation_hold" | "not_found" | "conflict" | "validation" | "suppressed" | "paused" | "quota" | "daily_limit" | "insufficient_balance" | "rate_limit" | "server" | "network" | "timeout" | "unknown";
|
|
10
10
|
/** Metadatos de la respuesta que no vienen en el cuerpo. */
|
|
11
11
|
export interface PartnerErrorMeta {
|
|
12
12
|
requestId?: string;
|
|
@@ -101,8 +101,17 @@ export declare class RateLimitError extends QuotaError {
|
|
|
101
101
|
kind: PartnerErrorKind;
|
|
102
102
|
}
|
|
103
103
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
104
|
+
* 429 `daily_limit`: el tenant llegó a su límite del día (crece solo con buena reputación). NO se
|
|
105
|
+
* reintenta: vuelve a intentar después de `resetsAt` (medianoche UTC) o manda un `batch`, que espera
|
|
106
|
+
* solo. Trae `limit` y `sentToday`.
|
|
107
|
+
*/
|
|
108
|
+
export declare class DailyLimitError extends QuotaError {
|
|
109
|
+
name: string;
|
|
110
|
+
kind: PartnerErrorKind;
|
|
111
|
+
get sentToday(): number | undefined;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 402 `insufficient_balance`: el saldo prepagado no alcanza. No se reintenta: recarga con `partner.topup()`. Trae `balanceCents` y `requiredCents`.
|
|
106
115
|
*/
|
|
107
116
|
export declare class InsufficientBalanceError extends PartnerApiError {
|
|
108
117
|
name: string;
|
|
@@ -373,6 +382,8 @@ export declare class MailMaskPartnerAdmin {
|
|
|
373
382
|
setReputationPolicy(partnerId: string, policy: ReputationPolicy | null): Promise<PartnerSummary>;
|
|
374
383
|
/** Sólo MailMask (admin): levanta cualquier pausa, también la de reputación. */
|
|
375
384
|
resumeTenant(partnerId: string, externalId: string): Promise<Tenant>;
|
|
385
|
+
/** Sólo MailMask: tope diario fijo del tenant, o `null` para volver al calentamiento. */
|
|
386
|
+
setTenantDailyLimit(partnerId: string, externalId: string, limit: number | null): Promise<Tenant>;
|
|
376
387
|
/**
|
|
377
388
|
* Sólo MailMask (admin): crea o adopta la hosted zone de la zona de respaldo (`marketing.denik.me`)
|
|
378
389
|
* y devuelve los NS que el partner tiene que delegar. Idempotente con la misma zona.
|
|
@@ -384,8 +395,6 @@ export declare class MailMaskPartnerAdmin {
|
|
|
384
395
|
getBalance(partnerId: string): Promise<PartnerBalanceDetail>;
|
|
385
396
|
/** Sólo MailMask (admin): abono (o cargo, negativo) manual. Con la misma `idempotencyKey` no se repite. */
|
|
386
397
|
adjustBalance(partnerId: string, input: AdjustBalanceRequest): Promise<PartnerBalanceDetail>;
|
|
387
|
-
/** Sólo MailMask (admin): prende o apaga el cobro por adelantado del partner. */
|
|
388
|
-
setPrepaidEnforced(partnerId: string, enforced: boolean): Promise<PartnerSummary>;
|
|
389
398
|
/** Liga de MercadoPago para recargar, con la llave del dueño. */
|
|
390
399
|
topup(partnerId: string, input: TopupRequest): Promise<TopupResponse>;
|
|
391
400
|
listCredentials(partnerId: string): Promise<ListCredentialsResponse>;
|