@primitivedotdev/sdk 0.12.0 → 0.14.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/api/generated/index.js +1 -1
- package/dist/api/generated/sdk.gen.js +91 -4
- package/dist/api/index.d.ts +2 -2
- package/dist/{api-CLLpjjWy.js → api-DH-YKt7a.js} +104 -5
- package/dist/{index-K4KbjppU.d.ts → index-Cts9r1sL.d.ts} +625 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/oclif/api-command.js +72 -12
- package/dist/oclif/commands/emails-latest.js +118 -0
- package/dist/oclif/commands/send.js +25 -4
- package/dist/oclif/commands/whoami.js +2 -3
- package/dist/oclif/index.js +69 -3
- package/dist/openapi/openapi.generated.js +570 -7
- package/dist/openapi/operations.generated.js +111 -2
- package/oclif.manifest.json +243 -14
- package/package.json +3 -3
|
@@ -532,8 +532,8 @@ export const openapiDocument = {
|
|
|
532
532
|
"/emails": {
|
|
533
533
|
"get": {
|
|
534
534
|
"operationId": "listEmails",
|
|
535
|
-
"summary": "List emails",
|
|
536
|
-
"description": "Returns a paginated list of received
|
|
535
|
+
"summary": "List inbound emails",
|
|
536
|
+
"description": "Returns a paginated list of INBOUND emails received at your\nverified domains. Outbound messages sent via /send-mail are not\nincluded; this endpoint is the inbox view, not a unified\nsend/receive history.\n\nSupports filtering by domain, status, date range, and free-text\nsearch across subject, sender, and recipient fields.\n",
|
|
537
537
|
"tags": [
|
|
538
538
|
"Emails"
|
|
539
539
|
],
|
|
@@ -1522,6 +1522,53 @@ export const openapiDocument = {
|
|
|
1522
1522
|
}
|
|
1523
1523
|
}
|
|
1524
1524
|
},
|
|
1525
|
+
"/send-permissions": {
|
|
1526
|
+
"get": {
|
|
1527
|
+
"operationId": "getSendPermissions",
|
|
1528
|
+
"summary": "List send-permission rules",
|
|
1529
|
+
"description": "Returns a flat list of rules describing every recipient the\ncaller may send to. Each rule has a `type`, a kind-specific\npayload, and a human-readable `description`. If any rule\nmatches the recipient, /send-mail will accept the send under\nthe recipient-scope check.\n\nThe endpoint is the answer to \"where can I send\" without\nexposing internal entitlement names. Agents that don't\nrecognize a `type` can still read the `description` prose\nand act on it.\n\nRule kinds, ordered broadest-first so an agent can stop\nscanning at the first match:\n\n 1. `any_recipient` (one entry, only when the org can send\n anywhere): every other rule below it is redundant.\n 2. `managed_zone` (always emitted, one per Primitive-managed\n zone): sends to any address at *.primitive.email or\n *.email.works always succeed; no entitlement required.\n 3. `your_domain` (one per active verified outbound domain\n owned by the org): sends to that domain are approved.\n 4. `address` (one per address that has authenticated\n inbound mail to the org, capped at `meta.address_cap`):\n sends to that exact address are approved.\n\nThe list is informational, not an authorization check.\n/send-mail remains the source of truth on whether an\nindividual send will succeed (it also enforces the\nfrom-address and the `send_mail` entitlement, which are\nnot recipient-scope concerns and are not represented here).\n",
|
|
1530
|
+
"tags": [
|
|
1531
|
+
"Sending"
|
|
1532
|
+
],
|
|
1533
|
+
"responses": {
|
|
1534
|
+
"200": {
|
|
1535
|
+
"description": "Send-permission rules for the caller's org",
|
|
1536
|
+
"content": {
|
|
1537
|
+
"application/json": {
|
|
1538
|
+
"schema": {
|
|
1539
|
+
"allOf": [
|
|
1540
|
+
{
|
|
1541
|
+
"$ref": "#/components/schemas/SuccessEnvelope"
|
|
1542
|
+
},
|
|
1543
|
+
{
|
|
1544
|
+
"type": "object",
|
|
1545
|
+
"properties": {
|
|
1546
|
+
"data": {
|
|
1547
|
+
"type": "array",
|
|
1548
|
+
"items": {
|
|
1549
|
+
"$ref": "#/components/schemas/SendPermissionRule"
|
|
1550
|
+
}
|
|
1551
|
+
},
|
|
1552
|
+
"meta": {
|
|
1553
|
+
"$ref": "#/components/schemas/SendPermissionsMeta"
|
|
1554
|
+
}
|
|
1555
|
+
},
|
|
1556
|
+
"required": [
|
|
1557
|
+
"data",
|
|
1558
|
+
"meta"
|
|
1559
|
+
]
|
|
1560
|
+
}
|
|
1561
|
+
]
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
},
|
|
1566
|
+
"401": {
|
|
1567
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
},
|
|
1525
1572
|
"/send-mail": {
|
|
1526
1573
|
"post": {
|
|
1527
1574
|
"operationId": "sendEmail",
|
|
@@ -1600,6 +1647,150 @@ export const openapiDocument = {
|
|
|
1600
1647
|
}
|
|
1601
1648
|
}
|
|
1602
1649
|
}
|
|
1650
|
+
},
|
|
1651
|
+
"/sent-emails": {
|
|
1652
|
+
"get": {
|
|
1653
|
+
"operationId": "listSentEmails",
|
|
1654
|
+
"summary": "List outbound sent emails",
|
|
1655
|
+
"description": "Returns a paginated list of OUTBOUND emails the caller's\norg has sent via /send-mail (and /emails/{id}/reply, which\nforwards through /send-mail). Includes every recorded\nattempt, including gate-denied attempts that the agent\nnever called and rows still in `queued` state.\n\nFor inbound mail received at your verified domains, see\n/emails. There is no unified send/receive history endpoint;\nthe two surfaces are intentionally separate because the\nunderlying tables, statuses, and lifecycle differ.\n\nEmail bodies (`body_text`, `body_html`) are NOT included on\nlist rows so a 50-row page can't balloon into a multi-MB\nresponse when sends are near the 5MB body cap. Use\n/sent-emails/{id} to fetch a single row with bodies, or\ncross-reference by `client_idempotency_key` if the caller\nalready has the body locally.\n",
|
|
1656
|
+
"tags": [
|
|
1657
|
+
"Sending"
|
|
1658
|
+
],
|
|
1659
|
+
"parameters": [
|
|
1660
|
+
{
|
|
1661
|
+
"$ref": "#/components/parameters/Cursor"
|
|
1662
|
+
},
|
|
1663
|
+
{
|
|
1664
|
+
"$ref": "#/components/parameters/Limit"
|
|
1665
|
+
},
|
|
1666
|
+
{
|
|
1667
|
+
"name": "status",
|
|
1668
|
+
"in": "query",
|
|
1669
|
+
"schema": {
|
|
1670
|
+
"$ref": "#/components/schemas/SentEmailStatus"
|
|
1671
|
+
},
|
|
1672
|
+
"description": "Filter to rows in this status. Useful for polling\nqueued rows that haven't transitioned, auditing\ngate-denied attempts, or listing only successful\ndeliveries.\n"
|
|
1673
|
+
},
|
|
1674
|
+
{
|
|
1675
|
+
"name": "request_id",
|
|
1676
|
+
"in": "query",
|
|
1677
|
+
"schema": {
|
|
1678
|
+
"type": "string",
|
|
1679
|
+
"format": "uuid"
|
|
1680
|
+
},
|
|
1681
|
+
"description": "Filter to the row matching a specific server-issued\n`request_id`. The /send-mail response surfaces\n`request_id` on every send; this lookup lets the\ncaller find the historical row for a given live call\nwithout remembering its `id`.\n"
|
|
1682
|
+
},
|
|
1683
|
+
{
|
|
1684
|
+
"name": "idempotency_key",
|
|
1685
|
+
"in": "query",
|
|
1686
|
+
"schema": {
|
|
1687
|
+
"type": "string",
|
|
1688
|
+
"minLength": 1,
|
|
1689
|
+
"maxLength": 255
|
|
1690
|
+
},
|
|
1691
|
+
"description": "Filter to rows with the given `client_idempotency_key`.\nMultiple rows can share a key (a retry that hit the\nidempotent-replay path returns the same row, but a\nretry with a DIFFERENT canonical payload under the\nsame key is rejected by /send-mail before the row is\nwritten, so duplicates are bounded).\n"
|
|
1692
|
+
},
|
|
1693
|
+
{
|
|
1694
|
+
"name": "date_from",
|
|
1695
|
+
"in": "query",
|
|
1696
|
+
"schema": {
|
|
1697
|
+
"type": "string",
|
|
1698
|
+
"format": "date-time"
|
|
1699
|
+
},
|
|
1700
|
+
"description": "Inclusive lower bound on `created_at`."
|
|
1701
|
+
},
|
|
1702
|
+
{
|
|
1703
|
+
"name": "date_to",
|
|
1704
|
+
"in": "query",
|
|
1705
|
+
"schema": {
|
|
1706
|
+
"type": "string",
|
|
1707
|
+
"format": "date-time"
|
|
1708
|
+
},
|
|
1709
|
+
"description": "Inclusive upper bound on `created_at`."
|
|
1710
|
+
}
|
|
1711
|
+
],
|
|
1712
|
+
"responses": {
|
|
1713
|
+
"200": {
|
|
1714
|
+
"description": "Page of sent-email summaries",
|
|
1715
|
+
"content": {
|
|
1716
|
+
"application/json": {
|
|
1717
|
+
"schema": {
|
|
1718
|
+
"allOf": [
|
|
1719
|
+
{
|
|
1720
|
+
"$ref": "#/components/schemas/ListEnvelope"
|
|
1721
|
+
},
|
|
1722
|
+
{
|
|
1723
|
+
"type": "object",
|
|
1724
|
+
"properties": {
|
|
1725
|
+
"data": {
|
|
1726
|
+
"type": "array",
|
|
1727
|
+
"items": {
|
|
1728
|
+
"$ref": "#/components/schemas/SentEmailSummary"
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
]
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
},
|
|
1738
|
+
"400": {
|
|
1739
|
+
"$ref": "#/components/responses/ValidationError"
|
|
1740
|
+
},
|
|
1741
|
+
"401": {
|
|
1742
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
},
|
|
1747
|
+
"/sent-emails/{id}": {
|
|
1748
|
+
"get": {
|
|
1749
|
+
"operationId": "getSentEmail",
|
|
1750
|
+
"summary": "Get a sent email by id",
|
|
1751
|
+
"description": "Returns the full sent-email record by id, including\n`body_text` and `body_html` (omitted from the listing\nendpoint to keep paginated responses small). Use this when\ndiagnosing a specific send, e.g. inspecting the receiver's\nSMTP response on a `bounced` row or pulling the gate\ndenial detail on a `gate_denied` row.\n",
|
|
1752
|
+
"tags": [
|
|
1753
|
+
"Sending"
|
|
1754
|
+
],
|
|
1755
|
+
"parameters": [
|
|
1756
|
+
{
|
|
1757
|
+
"$ref": "#/components/parameters/ResourceId"
|
|
1758
|
+
}
|
|
1759
|
+
],
|
|
1760
|
+
"responses": {
|
|
1761
|
+
"200": {
|
|
1762
|
+
"description": "Sent-email detail",
|
|
1763
|
+
"content": {
|
|
1764
|
+
"application/json": {
|
|
1765
|
+
"schema": {
|
|
1766
|
+
"allOf": [
|
|
1767
|
+
{
|
|
1768
|
+
"$ref": "#/components/schemas/SuccessEnvelope"
|
|
1769
|
+
},
|
|
1770
|
+
{
|
|
1771
|
+
"type": "object",
|
|
1772
|
+
"properties": {
|
|
1773
|
+
"data": {
|
|
1774
|
+
"$ref": "#/components/schemas/SentEmailDetail"
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
]
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
},
|
|
1783
|
+
"400": {
|
|
1784
|
+
"$ref": "#/components/responses/ValidationError"
|
|
1785
|
+
},
|
|
1786
|
+
"401": {
|
|
1787
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
1788
|
+
},
|
|
1789
|
+
"404": {
|
|
1790
|
+
"$ref": "#/components/responses/NotFound"
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1603
1794
|
}
|
|
1604
1795
|
},
|
|
1605
1796
|
"components": {
|
|
@@ -2432,7 +2623,8 @@ export const openapiDocument = {
|
|
|
2432
2623
|
]
|
|
2433
2624
|
},
|
|
2434
2625
|
"sender": {
|
|
2435
|
-
"type": "string"
|
|
2626
|
+
"type": "string",
|
|
2627
|
+
"description": "SMTP envelope sender (return-path) the inbound mail server\naccepted. For most legitimate mail this equals the bare\naddress in the From header; for mailing lists, bounce\nhandlers, and forwarders it is typically the bounce address\nrather than the human-visible sender.\n\nFor the parsed From-header value (with display name handling\nand a sender-fallback when the header is unparseable), GET\nthe email by id and use `from_email`.\n"
|
|
2436
2628
|
},
|
|
2437
2629
|
"recipient": {
|
|
2438
2630
|
"type": "string"
|
|
@@ -2523,7 +2715,8 @@ export const openapiDocument = {
|
|
|
2523
2715
|
"format": "uuid"
|
|
2524
2716
|
},
|
|
2525
2717
|
"sender": {
|
|
2526
|
-
"type": "string"
|
|
2718
|
+
"type": "string",
|
|
2719
|
+
"description": "SMTP envelope sender (return-path) the inbound mail server\naccepted. Same value as `smtp_mail_from`; both fields exist\nso protocol-aware tooling can use whichever name it expects.\n\nFor most legitimate mail this equals `from_email`; for\nmailing lists, bounce handlers, and forwarders it is\ntypically the bounce-handling address rather than the\nhuman-visible sender.\n\n**For the canonical \"who sent this email\" value, use\n`from_email`.**\n"
|
|
2527
2720
|
},
|
|
2528
2721
|
"recipient": {
|
|
2529
2722
|
"type": "string"
|
|
@@ -2645,7 +2838,8 @@ export const openapiDocument = {
|
|
|
2645
2838
|
"type": [
|
|
2646
2839
|
"string",
|
|
2647
2840
|
"null"
|
|
2648
|
-
]
|
|
2841
|
+
],
|
|
2842
|
+
"description": "SMTP envelope MAIL FROM (return-path), as accepted by the\ninbound mail server. Same value as `sender`; both fields\nexist so protocol-aware tooling can use whichever name it\nexpects.\n\nFor the canonical \"who sent this email\" value (display name\nstripped, From-header preferred), use `from_email`.\n"
|
|
2649
2843
|
},
|
|
2650
2844
|
"smtp_rcpt_to": {
|
|
2651
2845
|
"type": [
|
|
@@ -2660,7 +2854,8 @@ export const openapiDocument = {
|
|
|
2660
2854
|
"type": [
|
|
2661
2855
|
"string",
|
|
2662
2856
|
"null"
|
|
2663
|
-
]
|
|
2857
|
+
],
|
|
2858
|
+
"description": "Raw `From:` header from the message body, including any\ndisplay name (e.g. `\"Alice Example\" <alice@example.com>`).\nUse this when you need the display name for rendering.\n\nFor the bare email address (display name stripped), use\n`from_email`.\n"
|
|
2664
2859
|
},
|
|
2665
2860
|
"content_discarded_at": {
|
|
2666
2861
|
"type": [
|
|
@@ -2677,7 +2872,7 @@ export const openapiDocument = {
|
|
|
2677
2872
|
},
|
|
2678
2873
|
"from_email": {
|
|
2679
2874
|
"type": "string",
|
|
2680
|
-
"description": "
|
|
2875
|
+
"description": "Bare email address parsed from the `From:` header, with\ndisplay name stripped (e.g. `alice@example.com`). Falls\nback to `sender` (the SMTP envelope MAIL FROM) when the\n`From:` header cannot be parsed.\n\n**This is the canonical \"who sent this email\" field for\nmost use cases**, including comparing against allowlists,\nrouting replies, or displaying the sender to a user. Use\n`from_header` when you specifically need the display name,\nor `sender`/`smtp_mail_from` when you need the SMTP\nenvelope value (e.g. to follow a bounce).\n"
|
|
2681
2876
|
},
|
|
2682
2877
|
"to_email": {
|
|
2683
2878
|
"type": "string",
|
|
@@ -2816,10 +3011,12 @@ export const openapiDocument = {
|
|
|
2816
3011
|
},
|
|
2817
3012
|
"SentEmailStatus": {
|
|
2818
3013
|
"type": "string",
|
|
3014
|
+
"description": "Lifecycle status of a sent_emails row. Possible values:\n\n - `queued`: pre-call INSERT; the outbound agent has not\n yet replied.\n - `submitted_to_agent`: agent accepted; `queue_id` is set.\n - `agent_failed`: agent rejected; `error_code` and\n `error_message` carry the reason.\n - `gate_denied`: a recipient-scope gate denied the send;\n the agent was never called. The `gates` array carries\n the denial detail. /send-mail returns 403 in this case\n so callers see the denial synchronously; /sent-emails\n additionally records the row for historical lookup,\n which is when this status appears in a listing.\n - `unknown`: terminal indeterminate; the on-box log\n poller couldn't classify the receiver's response.\n - `delivered` / `bounced` / `deferred` / `wait_timeout`:\n terminal delivery outcomes (see DeliveryStatus).\n",
|
|
2819
3015
|
"enum": [
|
|
2820
3016
|
"queued",
|
|
2821
3017
|
"submitted_to_agent",
|
|
2822
3018
|
"agent_failed",
|
|
3019
|
+
"gate_denied",
|
|
2823
3020
|
"unknown",
|
|
2824
3021
|
"delivered",
|
|
2825
3022
|
"bounced",
|
|
@@ -2836,6 +3033,217 @@ export const openapiDocument = {
|
|
|
2836
3033
|
"wait_timeout"
|
|
2837
3034
|
]
|
|
2838
3035
|
},
|
|
3036
|
+
"SentEmailSummary": {
|
|
3037
|
+
"type": "object",
|
|
3038
|
+
"description": "List-row projection of a sent-email record. Drops\n`body_text` and `body_html` to keep paginated responses\nsmall; fetch /sent-emails/{id} for the full record with\nbodies.\n",
|
|
3039
|
+
"properties": {
|
|
3040
|
+
"id": {
|
|
3041
|
+
"type": "string",
|
|
3042
|
+
"format": "uuid"
|
|
3043
|
+
},
|
|
3044
|
+
"status": {
|
|
3045
|
+
"$ref": "#/components/schemas/SentEmailStatus"
|
|
3046
|
+
},
|
|
3047
|
+
"status_changed_at": {
|
|
3048
|
+
"type": "string",
|
|
3049
|
+
"format": "date-time",
|
|
3050
|
+
"description": "Timestamp of the most recent status transition.\nPolling clients should treat `status='queued'` AND\n`status_changed_at` older than 5 minutes as\n\"stuck-queued\" (the post-tx UPDATE failed and the\nactual delivery state is recoverable from on-box logs\nvia `queue_id` when populated, or `request_id`).\n"
|
|
3051
|
+
},
|
|
3052
|
+
"created_at": {
|
|
3053
|
+
"type": "string",
|
|
3054
|
+
"format": "date-time"
|
|
3055
|
+
},
|
|
3056
|
+
"updated_at": {
|
|
3057
|
+
"type": "string",
|
|
3058
|
+
"format": "date-time"
|
|
3059
|
+
},
|
|
3060
|
+
"client_idempotency_key": {
|
|
3061
|
+
"type": [
|
|
3062
|
+
"string",
|
|
3063
|
+
"null"
|
|
3064
|
+
],
|
|
3065
|
+
"description": "Effective idempotency key used for this send. If the\ncaller passed the `Idempotency-Key` header, this is\nthat value; otherwise it's a server-derived hash of\nthe canonical request payload.\n"
|
|
3066
|
+
},
|
|
3067
|
+
"content_hash": {
|
|
3068
|
+
"type": "string",
|
|
3069
|
+
"description": "Stable hash of the canonical send payload."
|
|
3070
|
+
},
|
|
3071
|
+
"from_header": {
|
|
3072
|
+
"type": "string",
|
|
3073
|
+
"description": "Raw `From:` header as sent on the wire, including any\ndisplay name (e.g. `\"Acme Support\" <agent@acme.test>`).\n"
|
|
3074
|
+
},
|
|
3075
|
+
"from_address": {
|
|
3076
|
+
"type": "string",
|
|
3077
|
+
"description": "Bare email address parsed from `from_header`."
|
|
3078
|
+
},
|
|
3079
|
+
"to_header": {
|
|
3080
|
+
"type": "string",
|
|
3081
|
+
"description": "Raw `To:` header as sent on the wire, including any\ndisplay name.\n"
|
|
3082
|
+
},
|
|
3083
|
+
"to_address": {
|
|
3084
|
+
"type": "string",
|
|
3085
|
+
"description": "Bare email address parsed from `to_header`."
|
|
3086
|
+
},
|
|
3087
|
+
"subject": {
|
|
3088
|
+
"type": "string"
|
|
3089
|
+
},
|
|
3090
|
+
"body_size_bytes": {
|
|
3091
|
+
"type": "integer",
|
|
3092
|
+
"description": "Total UTF-8 byte length of `body_text` + `body_html`.\nSurfaced on the list endpoint so callers can see \"this\nrow has a 4MB body\" without fetching it.\n"
|
|
3093
|
+
},
|
|
3094
|
+
"content_discarded_at": {
|
|
3095
|
+
"type": [
|
|
3096
|
+
"string",
|
|
3097
|
+
"null"
|
|
3098
|
+
],
|
|
3099
|
+
"format": "date-time",
|
|
3100
|
+
"description": "Timestamp at which the bodies were discarded by an\nentitlement-driven retention policy. Null when bodies\nare still present. The detail endpoint returns\nnull-valued `body_text`/`body_html` for discarded rows.\n"
|
|
3101
|
+
},
|
|
3102
|
+
"message_id": {
|
|
3103
|
+
"type": [
|
|
3104
|
+
"string",
|
|
3105
|
+
"null"
|
|
3106
|
+
],
|
|
3107
|
+
"description": "Wire-level Message-ID assigned to the outbound message\n(RFC 5322). Null on rows that never reached signing\n(queued, gate_denied, agent_failed before signing).\n"
|
|
3108
|
+
},
|
|
3109
|
+
"in_reply_to": {
|
|
3110
|
+
"type": [
|
|
3111
|
+
"string",
|
|
3112
|
+
"null"
|
|
3113
|
+
],
|
|
3114
|
+
"description": "Wire-level In-Reply-To header value, when this send\nwas a reply.\n"
|
|
3115
|
+
},
|
|
3116
|
+
"email_references": {
|
|
3117
|
+
"type": [
|
|
3118
|
+
"string",
|
|
3119
|
+
"null"
|
|
3120
|
+
],
|
|
3121
|
+
"description": "Wire-level References header value, when this send\nwas a reply.\n"
|
|
3122
|
+
},
|
|
3123
|
+
"in_reply_to_email_id": {
|
|
3124
|
+
"type": [
|
|
3125
|
+
"string",
|
|
3126
|
+
"null"
|
|
3127
|
+
],
|
|
3128
|
+
"format": "uuid",
|
|
3129
|
+
"description": "Reference to the inbound `emails.id` that this send\nreplied to, when known. Populated when the caller used\n/emails/{id}/reply or when /send-mail's `in_reply_to`\nmatched a stored inbound message_id in the same org.\n"
|
|
3130
|
+
},
|
|
3131
|
+
"queue_id": {
|
|
3132
|
+
"type": [
|
|
3133
|
+
"string",
|
|
3134
|
+
"null"
|
|
3135
|
+
],
|
|
3136
|
+
"description": "Message identifier assigned by Primitive's outbound\nrelay once the agent accepts the message. Null on\nqueued, gate_denied, and agent_failed rows.\n"
|
|
3137
|
+
},
|
|
3138
|
+
"smtp_response_code": {
|
|
3139
|
+
"type": [
|
|
3140
|
+
"integer",
|
|
3141
|
+
"null"
|
|
3142
|
+
],
|
|
3143
|
+
"description": "Receiver's 3-digit SMTP code (e.g. 250, 550, 451).\nPopulated on terminal delivery statuses; may be null\non a deferred where the agent never got an SMTP-level\nresponse (TCP refused, DNS failed, TLS handshake\nfailed). `smtp_response_text` still carries Postfix's\ndescriptive text in those cases.\n"
|
|
3144
|
+
},
|
|
3145
|
+
"smtp_response_text": {
|
|
3146
|
+
"type": [
|
|
3147
|
+
"string",
|
|
3148
|
+
"null"
|
|
3149
|
+
],
|
|
3150
|
+
"description": "Free-form text portion of the receiver's SMTP\nresponse. The most useful debugging signal on a\n`bounced` or `deferred` row.\n"
|
|
3151
|
+
},
|
|
3152
|
+
"smtp_enhanced_status_code": {
|
|
3153
|
+
"type": [
|
|
3154
|
+
"string",
|
|
3155
|
+
"null"
|
|
3156
|
+
],
|
|
3157
|
+
"description": "RFC 3463 enhanced status code (e.g. `5.1.1` for \"Bad\ndestination mailbox address\"). Distinct from\n`smtp_response_code`: the basic 3-digit code is coarse\n(550 = \"permanent failure\"), the enhanced code is\nfiner-grained.\n"
|
|
3158
|
+
},
|
|
3159
|
+
"dkim_selector": {
|
|
3160
|
+
"type": [
|
|
3161
|
+
"string",
|
|
3162
|
+
"null"
|
|
3163
|
+
],
|
|
3164
|
+
"description": "DKIM selector used to sign the outbound message.\nPublic DNS data; useful for diagnosing why a downstream\nverifier rejected the signature.\n"
|
|
3165
|
+
},
|
|
3166
|
+
"dkim_domain": {
|
|
3167
|
+
"type": [
|
|
3168
|
+
"string",
|
|
3169
|
+
"null"
|
|
3170
|
+
],
|
|
3171
|
+
"description": "DKIM signing domain."
|
|
3172
|
+
},
|
|
3173
|
+
"error_code": {
|
|
3174
|
+
"type": [
|
|
3175
|
+
"string",
|
|
3176
|
+
"null"
|
|
3177
|
+
],
|
|
3178
|
+
"description": "Stable public error code on `agent_failed` rows. The\nagent's internal codes are remapped to a stable public\ntaxonomy (see `publicAgentError` in the server) so this\nfield is safe to branch on across agent versions.\n"
|
|
3179
|
+
},
|
|
3180
|
+
"error_message": {
|
|
3181
|
+
"type": [
|
|
3182
|
+
"string",
|
|
3183
|
+
"null"
|
|
3184
|
+
],
|
|
3185
|
+
"description": "Free-form error message accompanying `error_code`."
|
|
3186
|
+
},
|
|
3187
|
+
"gates": {
|
|
3188
|
+
"type": [
|
|
3189
|
+
"array",
|
|
3190
|
+
"null"
|
|
3191
|
+
],
|
|
3192
|
+
"items": {
|
|
3193
|
+
"$ref": "#/components/schemas/GateDenial"
|
|
3194
|
+
},
|
|
3195
|
+
"description": "Gate-denial detail on `gate_denied` rows. Mirrors the\nsynchronous /send-mail 403 contract so a caller's\nGateDenial handler is the same across live denies and\nhistorical lookups. Null on every other status.\n"
|
|
3196
|
+
},
|
|
3197
|
+
"request_id": {
|
|
3198
|
+
"type": [
|
|
3199
|
+
"string",
|
|
3200
|
+
"null"
|
|
3201
|
+
],
|
|
3202
|
+
"description": "Server-issued request identifier from the original\n/send-mail call. Surfaced as the `X-Request-Id`\nresponse header on the live send and recorded here\nfor support escalation.\n"
|
|
3203
|
+
}
|
|
3204
|
+
},
|
|
3205
|
+
"required": [
|
|
3206
|
+
"id",
|
|
3207
|
+
"status",
|
|
3208
|
+
"status_changed_at",
|
|
3209
|
+
"created_at",
|
|
3210
|
+
"updated_at",
|
|
3211
|
+
"content_hash",
|
|
3212
|
+
"from_header",
|
|
3213
|
+
"from_address",
|
|
3214
|
+
"to_header",
|
|
3215
|
+
"to_address",
|
|
3216
|
+
"subject",
|
|
3217
|
+
"body_size_bytes"
|
|
3218
|
+
]
|
|
3219
|
+
},
|
|
3220
|
+
"SentEmailDetail": {
|
|
3221
|
+
"description": "Full sent-email record, including `body_text` and\n`body_html`. Returned by /sent-emails/{id}.\n",
|
|
3222
|
+
"allOf": [
|
|
3223
|
+
{
|
|
3224
|
+
"$ref": "#/components/schemas/SentEmailSummary"
|
|
3225
|
+
},
|
|
3226
|
+
{
|
|
3227
|
+
"type": "object",
|
|
3228
|
+
"properties": {
|
|
3229
|
+
"body_text": {
|
|
3230
|
+
"type": [
|
|
3231
|
+
"string",
|
|
3232
|
+
"null"
|
|
3233
|
+
],
|
|
3234
|
+
"description": "Plain-text body sent on the wire. Null when the\nsend carried only an HTML body, or when bodies have\nbeen discarded post-send (`content_discarded_at`\nset).\n"
|
|
3235
|
+
},
|
|
3236
|
+
"body_html": {
|
|
3237
|
+
"type": [
|
|
3238
|
+
"string",
|
|
3239
|
+
"null"
|
|
3240
|
+
],
|
|
3241
|
+
"description": "HTML body sent on the wire. Null when the send\ncarried only a plain-text body, or when bodies\nhave been discarded post-send.\n"
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
]
|
|
3246
|
+
},
|
|
2839
3247
|
"ReplyInput": {
|
|
2840
3248
|
"type": "object",
|
|
2841
3249
|
"additionalProperties": false,
|
|
@@ -2871,6 +3279,10 @@ export const openapiDocument = {
|
|
|
2871
3279
|
"status": {
|
|
2872
3280
|
"$ref": "#/components/schemas/SentEmailStatus"
|
|
2873
3281
|
},
|
|
3282
|
+
"from": {
|
|
3283
|
+
"type": "string",
|
|
3284
|
+
"description": "Bare from-address actually written on the wire. Echoed\non every success branch so callers can confirm what\nwent out, particularly useful for the /emails/{id}/reply\npath where `from` is server-derived from the inbound's\nrecipient when the caller doesn't override.\n\nFor sends where the caller passed a from-header that\nincluded a display name (e.g. `\"Acme Support\" <support@acme.test>`),\nthis field is the parsed bare address (`support@acme.test`).\nThe display name was sent on the wire intact; this field\njust makes the address easy to compare against allowlists.\n"
|
|
3285
|
+
},
|
|
2874
3286
|
"queue_id": {
|
|
2875
3287
|
"type": [
|
|
2876
3288
|
"string",
|
|
@@ -2926,6 +3338,7 @@ export const openapiDocument = {
|
|
|
2926
3338
|
"required": [
|
|
2927
3339
|
"id",
|
|
2928
3340
|
"status",
|
|
3341
|
+
"from",
|
|
2929
3342
|
"queue_id",
|
|
2930
3343
|
"accepted",
|
|
2931
3344
|
"rejected",
|
|
@@ -2935,6 +3348,156 @@ export const openapiDocument = {
|
|
|
2935
3348
|
"idempotent_replay"
|
|
2936
3349
|
]
|
|
2937
3350
|
},
|
|
3351
|
+
"SendPermissionRule": {
|
|
3352
|
+
"description": "One recipient-scope rule describing a destination the caller\nmay send to. Discriminated on `type`. Each rule carries a\nhuman-prose `description` field intended for display.\n\nRule kinds are stable within an SDK release. A response\ncontaining a `type` value not enumerated in this schema\nmeans the server is running a newer version than the SDK;\nupgrade the SDK to the release that matches the server's\nschema. Strict-parsing SDKs (Go, Python) will raise a\ndecode error in that case rather than silently dropping\nthe unknown rule, since silent drops would let an outbound\nagent reason from an incomplete view of its own permissions.\n",
|
|
3353
|
+
"discriminator": {
|
|
3354
|
+
"propertyName": "type",
|
|
3355
|
+
"mapping": {
|
|
3356
|
+
"any_recipient": "#/components/schemas/SendPermissionAnyRecipient",
|
|
3357
|
+
"managed_zone": "#/components/schemas/SendPermissionManagedZone",
|
|
3358
|
+
"your_domain": "#/components/schemas/SendPermissionYourDomain",
|
|
3359
|
+
"address": "#/components/schemas/SendPermissionAddress"
|
|
3360
|
+
}
|
|
3361
|
+
},
|
|
3362
|
+
"oneOf": [
|
|
3363
|
+
{
|
|
3364
|
+
"$ref": "#/components/schemas/SendPermissionAnyRecipient"
|
|
3365
|
+
},
|
|
3366
|
+
{
|
|
3367
|
+
"$ref": "#/components/schemas/SendPermissionManagedZone"
|
|
3368
|
+
},
|
|
3369
|
+
{
|
|
3370
|
+
"$ref": "#/components/schemas/SendPermissionYourDomain"
|
|
3371
|
+
},
|
|
3372
|
+
{
|
|
3373
|
+
"$ref": "#/components/schemas/SendPermissionAddress"
|
|
3374
|
+
}
|
|
3375
|
+
]
|
|
3376
|
+
},
|
|
3377
|
+
"SendPermissionAnyRecipient": {
|
|
3378
|
+
"type": "object",
|
|
3379
|
+
"description": "The caller can send to any recipient. When this rule is\npresent, every other rule in the response is redundant.\n",
|
|
3380
|
+
"properties": {
|
|
3381
|
+
"type": {
|
|
3382
|
+
"type": "string",
|
|
3383
|
+
"enum": [
|
|
3384
|
+
"any_recipient"
|
|
3385
|
+
]
|
|
3386
|
+
},
|
|
3387
|
+
"description": {
|
|
3388
|
+
"type": "string",
|
|
3389
|
+
"description": "Human-prose summary of the rule."
|
|
3390
|
+
}
|
|
3391
|
+
},
|
|
3392
|
+
"required": [
|
|
3393
|
+
"type",
|
|
3394
|
+
"description"
|
|
3395
|
+
]
|
|
3396
|
+
},
|
|
3397
|
+
"SendPermissionManagedZone": {
|
|
3398
|
+
"type": "object",
|
|
3399
|
+
"description": "The caller can send to any address at the named\nPrimitive-managed zone. Always emitted (no entitlement\nrequired) because Primitive owns the zone and every mailbox\nbelongs to a Primitive customer by construction.\n",
|
|
3400
|
+
"properties": {
|
|
3401
|
+
"type": {
|
|
3402
|
+
"type": "string",
|
|
3403
|
+
"enum": [
|
|
3404
|
+
"managed_zone"
|
|
3405
|
+
]
|
|
3406
|
+
},
|
|
3407
|
+
"zone": {
|
|
3408
|
+
"type": "string",
|
|
3409
|
+
"description": "The managed apex domain. Sends are accepted to any\naddress at the apex itself or any subdomain (e.g.\n`alice@primitive.email` and `alice@acme.primitive.email`\nboth match the `primitive.email` zone rule).\n"
|
|
3410
|
+
},
|
|
3411
|
+
"description": {
|
|
3412
|
+
"type": "string",
|
|
3413
|
+
"description": "Human-prose summary of the rule."
|
|
3414
|
+
}
|
|
3415
|
+
},
|
|
3416
|
+
"required": [
|
|
3417
|
+
"type",
|
|
3418
|
+
"zone",
|
|
3419
|
+
"description"
|
|
3420
|
+
]
|
|
3421
|
+
},
|
|
3422
|
+
"SendPermissionYourDomain": {
|
|
3423
|
+
"type": "object",
|
|
3424
|
+
"description": "The caller can send to any address at one of their own\nverified outbound domains. Emitted once per active row in\nthe org's `domains` table.\n",
|
|
3425
|
+
"properties": {
|
|
3426
|
+
"type": {
|
|
3427
|
+
"type": "string",
|
|
3428
|
+
"enum": [
|
|
3429
|
+
"your_domain"
|
|
3430
|
+
]
|
|
3431
|
+
},
|
|
3432
|
+
"domain": {
|
|
3433
|
+
"type": "string",
|
|
3434
|
+
"description": "A verified outbound domain owned by the caller's org."
|
|
3435
|
+
},
|
|
3436
|
+
"description": {
|
|
3437
|
+
"type": "string",
|
|
3438
|
+
"description": "Human-prose summary of the rule."
|
|
3439
|
+
}
|
|
3440
|
+
},
|
|
3441
|
+
"required": [
|
|
3442
|
+
"type",
|
|
3443
|
+
"domain",
|
|
3444
|
+
"description"
|
|
3445
|
+
]
|
|
3446
|
+
},
|
|
3447
|
+
"SendPermissionAddress": {
|
|
3448
|
+
"type": "object",
|
|
3449
|
+
"description": "The caller can send to a specific address that has\nauthenticated inbound mail to the org. Emitted once per row\nin the org's `known_send_addresses` table, capped at\n`meta.address_cap`.\n",
|
|
3450
|
+
"properties": {
|
|
3451
|
+
"type": {
|
|
3452
|
+
"type": "string",
|
|
3453
|
+
"enum": [
|
|
3454
|
+
"address"
|
|
3455
|
+
]
|
|
3456
|
+
},
|
|
3457
|
+
"address": {
|
|
3458
|
+
"type": "string",
|
|
3459
|
+
"description": "The bare email address this rule grants sends to."
|
|
3460
|
+
},
|
|
3461
|
+
"last_received_at": {
|
|
3462
|
+
"type": "string",
|
|
3463
|
+
"format": "date-time",
|
|
3464
|
+
"description": "Most recent inbound email from this address that\nauthenticated successfully (DMARC pass + DKIM/SPF\nalignment). Updated on each new authenticated receipt.\n"
|
|
3465
|
+
},
|
|
3466
|
+
"received_count": {
|
|
3467
|
+
"type": "integer",
|
|
3468
|
+
"description": "Total number of authenticated inbound emails from this\naddress. Increments only when `last_received_at` advances.\n"
|
|
3469
|
+
},
|
|
3470
|
+
"description": {
|
|
3471
|
+
"type": "string",
|
|
3472
|
+
"description": "Human-prose summary of the rule."
|
|
3473
|
+
}
|
|
3474
|
+
},
|
|
3475
|
+
"required": [
|
|
3476
|
+
"type",
|
|
3477
|
+
"address",
|
|
3478
|
+
"last_received_at",
|
|
3479
|
+
"received_count",
|
|
3480
|
+
"description"
|
|
3481
|
+
]
|
|
3482
|
+
},
|
|
3483
|
+
"SendPermissionsMeta": {
|
|
3484
|
+
"type": "object",
|
|
3485
|
+
"description": "Response metadata for /send-permissions. The `address_cap`\nbounds the size of the `address` rule subset; orgs with more\nthan `address_cap` known addresses almost always also hold a\nbroader rule type (`any_recipient` or `your_domain`), so the\ncap is a response-size bound rather than a meaningful\nproduct limit.\n",
|
|
3486
|
+
"properties": {
|
|
3487
|
+
"address_cap": {
|
|
3488
|
+
"type": "integer",
|
|
3489
|
+
"description": "Maximum number of `address` rules included in `data`."
|
|
3490
|
+
},
|
|
3491
|
+
"truncated": {
|
|
3492
|
+
"type": "boolean",
|
|
3493
|
+
"description": "True when the org has more than `address_cap` known\naddresses and the list was truncated. False when every\nknown address is represented or when the org holds no\naddress rules at all.\n"
|
|
3494
|
+
}
|
|
3495
|
+
},
|
|
3496
|
+
"required": [
|
|
3497
|
+
"address_cap",
|
|
3498
|
+
"truncated"
|
|
3499
|
+
]
|
|
3500
|
+
},
|
|
2938
3501
|
"Endpoint": {
|
|
2939
3502
|
"type": "object",
|
|
2940
3503
|
"properties": {
|