@primitivedotdev/sdk 0.9.0 → 0.11.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.
@@ -842,6 +842,96 @@ export const openapiDocument = {
842
842
  }
843
843
  }
844
844
  },
845
+ "/emails/{id}/reply": {
846
+ "parameters": [
847
+ {
848
+ "$ref": "#/components/parameters/ResourceId"
849
+ }
850
+ ],
851
+ "post": {
852
+ "operationId": "replyToEmail",
853
+ "summary": "Reply to an inbound email",
854
+ "description": "Sends an outbound reply to the inbound email identified by `id`.\nThreading headers (`In-Reply-To`, `References`), recipient\nderivation (Reply-To, then From, then bare sender), and the\n`Re:` subject prefix are all derived server-side from the\nstored inbound row. The request body carries only the message\nbody and optional `wait` flag; passing any header or recipient\noverride is rejected by the schema (`additionalProperties:\nfalse`).\n\nForwards through the same gates as `/send-mail`: the response\nstatus, error envelope, and `idempotent_replay` flag mirror\nthe send-mail contract verbatim.\n",
855
+ "tags": [
856
+ "Sending"
857
+ ],
858
+ "requestBody": {
859
+ "required": true,
860
+ "content": {
861
+ "application/json": {
862
+ "schema": {
863
+ "$ref": "#/components/schemas/ReplyInput"
864
+ }
865
+ }
866
+ }
867
+ },
868
+ "responses": {
869
+ "200": {
870
+ "description": "Outbound relay result",
871
+ "content": {
872
+ "application/json": {
873
+ "schema": {
874
+ "allOf": [
875
+ {
876
+ "$ref": "#/components/schemas/SuccessEnvelope"
877
+ },
878
+ {
879
+ "type": "object",
880
+ "properties": {
881
+ "data": {
882
+ "$ref": "#/components/schemas/SendMailResult"
883
+ }
884
+ }
885
+ }
886
+ ]
887
+ }
888
+ }
889
+ }
890
+ },
891
+ "400": {
892
+ "$ref": "#/components/responses/ValidationError"
893
+ },
894
+ "401": {
895
+ "$ref": "#/components/responses/Unauthorized"
896
+ },
897
+ "403": {
898
+ "$ref": "#/components/responses/Forbidden"
899
+ },
900
+ "404": {
901
+ "$ref": "#/components/responses/NotFound"
902
+ },
903
+ "422": {
904
+ "description": "Inbound is not repliable: the row exists but lacks a\n`message_id` (no thread anchor) or a `recipient` (cannot\nderive the From address).\n",
905
+ "content": {
906
+ "application/json": {
907
+ "schema": {
908
+ "$ref": "#/components/schemas/ErrorResponse"
909
+ },
910
+ "example": {
911
+ "success": false,
912
+ "error": {
913
+ "code": "inbound_not_repliable",
914
+ "message": "inbound has no Message-ID; cannot anchor a reply thread"
915
+ }
916
+ }
917
+ }
918
+ }
919
+ },
920
+ "429": {
921
+ "$ref": "#/components/responses/RateLimited"
922
+ },
923
+ "500": {
924
+ "$ref": "#/components/responses/InternalError"
925
+ },
926
+ "502": {
927
+ "$ref": "#/components/responses/BadGateway"
928
+ },
929
+ "503": {
930
+ "$ref": "#/components/responses/ServiceUnavailable"
931
+ }
932
+ }
933
+ }
934
+ },
845
935
  "/emails/{id}/replay": {
846
936
  "parameters": [
847
937
  {
@@ -1819,7 +1909,8 @@ export const openapiDocument = {
1819
1909
  "outbound_key_invalid",
1820
1910
  "outbound_capacity_exhausted",
1821
1911
  "outbound_response_malformed",
1822
- "outbound_relay_failed"
1912
+ "outbound_relay_failed",
1913
+ "inbound_not_repliable"
1823
1914
  ]
1824
1915
  },
1825
1916
  "message": {
@@ -2443,6 +2534,20 @@ export const openapiDocument = {
2443
2534
  "null"
2444
2535
  ]
2445
2536
  },
2537
+ "body_text": {
2538
+ "type": [
2539
+ "string",
2540
+ "null"
2541
+ ],
2542
+ "description": "Plain-text body parsed from the inbound MIME, matching the `email.parsed.body_text` field on the webhook payload. Null when the message had no text part or parsing failed."
2543
+ },
2544
+ "body_html": {
2545
+ "type": [
2546
+ "string",
2547
+ "null"
2548
+ ],
2549
+ "description": "HTML body parsed from the inbound MIME, matching the `email.parsed.body_html` field on the webhook payload. Null when the message had no HTML part or parsing failed."
2550
+ },
2446
2551
  "status": {
2447
2552
  "type": "string",
2448
2553
  "enum": [
@@ -2577,6 +2682,17 @@ export const openapiDocument = {
2577
2682
  "to_email": {
2578
2683
  "type": "string",
2579
2684
  "description": "Parsed to address (same as recipient)"
2685
+ },
2686
+ "from_known_address": {
2687
+ "type": "boolean",
2688
+ "description": "True when the inbound's sender address has a matching grant\nin the org's known-send-addresses list. Advisory: a true\nvalue does not by itself guarantee that a reply will be\naccepted by send-mail's gates; the per-send check at send\ntime remains authoritative.\n"
2689
+ },
2690
+ "replies": {
2691
+ "type": "array",
2692
+ "description": "Sent emails recorded as replies to this inbound, in send\norder (ascending). Populated when a customer's send-mail\nrequest carries an `in_reply_to` Message-ID that matches\nthis inbound's `message_id` in the same org. Includes\nattempts that were gate-denied, so the array reflects every\nrecorded reply attempt regardless of outcome.\n",
2693
+ "items": {
2694
+ "$ref": "#/components/schemas/EmailDetailReply"
2695
+ }
2580
2696
  }
2581
2697
  },
2582
2698
  "required": [
@@ -2589,7 +2705,48 @@ export const openapiDocument = {
2589
2705
  "received_at",
2590
2706
  "webhook_attempt_count",
2591
2707
  "from_email",
2592
- "to_email"
2708
+ "to_email",
2709
+ "replies"
2710
+ ]
2711
+ },
2712
+ "EmailDetailReply": {
2713
+ "type": "object",
2714
+ "properties": {
2715
+ "id": {
2716
+ "type": "string",
2717
+ "format": "uuid",
2718
+ "description": "Sent-email row id."
2719
+ },
2720
+ "status": {
2721
+ "$ref": "#/components/schemas/SentEmailStatus"
2722
+ },
2723
+ "to_address": {
2724
+ "type": "string",
2725
+ "description": "Recipient address as recorded on the sent_emails row."
2726
+ },
2727
+ "subject": {
2728
+ "type": [
2729
+ "string",
2730
+ "null"
2731
+ ]
2732
+ },
2733
+ "created_at": {
2734
+ "type": "string",
2735
+ "format": "date-time"
2736
+ },
2737
+ "queue_id": {
2738
+ "type": [
2739
+ "string",
2740
+ "null"
2741
+ ],
2742
+ "description": "Outbound relay queue identifier when available."
2743
+ }
2744
+ },
2745
+ "required": [
2746
+ "id",
2747
+ "status",
2748
+ "to_address",
2749
+ "created_at"
2593
2750
  ]
2594
2751
  },
2595
2752
  "SendMailInput": {
@@ -2679,6 +2836,31 @@ export const openapiDocument = {
2679
2836
  "wait_timeout"
2680
2837
  ]
2681
2838
  },
2839
+ "ReplyInput": {
2840
+ "type": "object",
2841
+ "additionalProperties": false,
2842
+ "description": "Body shape for `/emails/{id}/reply`. Intentionally narrow:\nrecipients (`to`), subject, and threading headers\n(`in_reply_to`, `references`) are derived server-side from\nthe inbound row referenced by the path id and are rejected by\n`additionalProperties` if passed (returns 400).\n\n`from` IS allowed because of legitimate use cases (display-name\naddition, replying from a different verified outbound address,\nmulti-team triage). Send-mail's per-send `canSendFrom` gate\nvalidates the from-domain regardless, so the override carries\nno extra privilege.\n",
2843
+ "properties": {
2844
+ "body_text": {
2845
+ "type": "string",
2846
+ "description": "Plain-text reply body. At least one of body_text or body_html is required. The combined UTF-8 byte length of body_text and body_html must be at most 262144 bytes (same cap as send-mail)."
2847
+ },
2848
+ "body_html": {
2849
+ "type": "string",
2850
+ "description": "HTML reply body. At least one of body_text or body_html is required."
2851
+ },
2852
+ "from": {
2853
+ "type": "string",
2854
+ "minLength": 3,
2855
+ "maxLength": 998,
2856
+ "description": "Optional override for the reply's From header. Defaults to\nthe inbound's recipient. Use to add a display name (`\"Acme\nSupport\" <agent@company.com>`) or to reply from a different\nverified outbound address (e.g. multi-team routing where\nsupport@ triages to billing@). The from-domain must be a\nverified outbound domain for your org, same as send-mail.\n"
2857
+ },
2858
+ "wait": {
2859
+ "type": "boolean",
2860
+ "description": "When true, wait for the first downstream SMTP delivery outcome before returning, mirroring the send-mail `wait` semantics."
2861
+ }
2862
+ }
2863
+ },
2682
2864
  "SendMailResult": {
2683
2865
  "type": "object",
2684
2866
  "properties": {
@@ -2735,6 +2917,10 @@ export const openapiDocument = {
2735
2917
  "smtp_response_text": {
2736
2918
  "type": "string",
2737
2919
  "description": "SMTP response text from the first downstream delivery outcome when wait is true."
2920
+ },
2921
+ "idempotent_replay": {
2922
+ "type": "boolean",
2923
+ "description": "True when the response replays a previously-recorded send\nkeyed by `client_idempotency_key` (same key, same canonical\npayload). False on a fresh send and on gate-denied\nresponses. Lets callers branch on cache state without\ndiffing fields.\n"
2738
2924
  }
2739
2925
  },
2740
2926
  "required": [
@@ -2745,7 +2931,8 @@ export const openapiDocument = {
2745
2931
  "rejected",
2746
2932
  "client_idempotency_key",
2747
2933
  "request_id",
2748
- "content_hash"
2934
+ "content_hash",
2935
+ "idempotent_replay"
2749
2936
  ]
2750
2937
  },
2751
2938
  "Endpoint": {
@@ -752,6 +752,55 @@ export const operationManifest = [
752
752
  "tag": "Filters",
753
753
  "tagCommand": "filters"
754
754
  },
755
+ {
756
+ "binaryResponse": false,
757
+ "bodyRequired": true,
758
+ "command": "reply-to-email",
759
+ "description": "Sends an outbound reply to the inbound email identified by `id`.\nThreading headers (`In-Reply-To`, `References`), recipient\nderivation (Reply-To, then From, then bare sender), and the\n`Re:` subject prefix are all derived server-side from the\nstored inbound row. The request body carries only the message\nbody and optional `wait` flag; passing any header or recipient\noverride is rejected by the schema (`additionalProperties:\nfalse`).\n\nForwards through the same gates as `/send-mail`: the response\nstatus, error envelope, and `idempotent_replay` flag mirror\nthe send-mail contract verbatim.\n",
760
+ "hasJsonBody": true,
761
+ "method": "POST",
762
+ "operationId": "replyToEmail",
763
+ "path": "/emails/{id}/reply",
764
+ "pathParams": [
765
+ {
766
+ "description": "Resource UUID",
767
+ "enum": null,
768
+ "name": "id",
769
+ "required": true,
770
+ "type": "string"
771
+ }
772
+ ],
773
+ "queryParams": [],
774
+ "requestSchema": {
775
+ "type": "object",
776
+ "additionalProperties": false,
777
+ "description": "Body shape for `/emails/{id}/reply`. Intentionally narrow:\nrecipients (`to`), subject, and threading headers\n(`in_reply_to`, `references`) are derived server-side from\nthe inbound row referenced by the path id and are rejected by\n`additionalProperties` if passed (returns 400).\n\n`from` IS allowed because of legitimate use cases (display-name\naddition, replying from a different verified outbound address,\nmulti-team triage). Send-mail's per-send `canSendFrom` gate\nvalidates the from-domain regardless, so the override carries\nno extra privilege.\n",
778
+ "properties": {
779
+ "body_text": {
780
+ "type": "string",
781
+ "description": "Plain-text reply body. At least one of body_text or body_html is required. The combined UTF-8 byte length of body_text and body_html must be at most 262144 bytes (same cap as send-mail)."
782
+ },
783
+ "body_html": {
784
+ "type": "string",
785
+ "description": "HTML reply body. At least one of body_text or body_html is required."
786
+ },
787
+ "from": {
788
+ "type": "string",
789
+ "minLength": 3,
790
+ "maxLength": 998,
791
+ "description": "Optional override for the reply's From header. Defaults to\nthe inbound's recipient. Use to add a display name (`\"Acme\nSupport\" <agent@company.com>`) or to reply from a different\nverified outbound address (e.g. multi-team routing where\nsupport@ triages to billing@). The from-domain must be a\nverified outbound domain for your org, same as send-mail.\n"
792
+ },
793
+ "wait": {
794
+ "type": "boolean",
795
+ "description": "When true, wait for the first downstream SMTP delivery outcome before returning, mirroring the send-mail `wait` semantics."
796
+ }
797
+ }
798
+ },
799
+ "sdkName": "replyToEmail",
800
+ "summary": "Reply to an inbound email",
801
+ "tag": "Sending",
802
+ "tagCommand": "sending"
803
+ },
755
804
  {
756
805
  "binaryResponse": false,
757
806
  "bodyRequired": true,