Skip to content
Norbelys
Esc
↑↓navigate↵open⌘Jpreview

Release a message's holds.

A recipient is held when evidence about this message said its mailbox was full, its server asked to come back later, or its domain had no mail route: mail to the address waits until a later success of the message lifts the hold, the hold’s time runs out, or a person who knows better releases it here. Every open hold of the message is resolved as manual, so mail to those addresses flows again, and the evidence is kept in the workspace’s audit log. A message without open holds is answered as it is.

POST/v1/messages/{id}/release_holds
Authorization
AuthorizationBearer token · headerrequired

An API key (nb_live_…, nb_test_…), a workspace token (nbs_…) or a CLI token (nbc_…).

Path parameters
idId_Messagerequired

The message id (msg_…).

matches ^msg_[0-9a-f]{32}$
Header parameters
Idempotency-Keystringrequired

A stable key for this logical request; reuse it when retrying.

min length 1 · max length 128 · matches ^[!-~]+$
Request body
requiredapplication/json
evidencestringrequired

What shows the holds no longer apply, for the record: what the person checked. At most 2,000 characters.

Responses
200

The message, its holds released.

attemptsMessageAttemptsrequired

A message's latest attempts.

Show properties
dataAttemptObject[]required

At most 20, newest first.

max items 20
Show properties
Array of AttemptObject
categoryEvidenceCategory | null
Show properties
One of:
EvidenceCategory
string
null
null
claimed_atTimestamprequired
connection_idId_Connectionrequired
matches ^con_[0-9a-f]{32}$
diagnosticstring | null

The provider's words, bounded and redacted.

enhanced_statusstring | null
finished_atTimestamp | null
Show properties
One of:
Timestamp
Timestamp
null
null
idId_Attemptrequired
matches ^att_[0-9a-f]{32}$
numberinteger<int32>required

1 for the message's first attempt.

outcomeAttemptOutcome | null
Show properties
One of:
AttemptOutcome
string
null
null
phaseSubmissionPhase | null
Show properties
One of:
SubmissionPhase
string
null
null
provider_message_idstring | null

The provider's id of the accepted message, when it returns one.

recipient_countinteger<int32>required
smtp_codeinteger<int32> | null
started_atTimestamp | null
Show properties
One of:
Timestamp
Timestamp
null
null
has_morebooleanrequired

More attempts exist than data shows; read them through an export.

attempts_countinteger<int64>required

Every attempt it had.

bccstring[]required
campaign_idId_Campaign | null
Show properties
One of:
Id_Campaign
string
null
null
ccstring[]required
connection_idId_Connectionrequired
matches ^con_[0-9a-f]{32}$
created_atTimestamprequired
enrollment_idId_Enrollment | null
Show properties
One of:
Id_Enrollment
string
null
null
eventsMessageEventsrequired

A message's first delivery events.

Show properties
dataDeliveryEventObject[]required

At most 20, in the order they were observed.

max items 20
Show properties
Array of DeliveryEventObject
actionDsnAction | null
Show properties
One of:
DsnAction
string
null
null
attempt_numberinteger<int32> | null

The attempt it comes from, when its source is an attempt.

categoryEvidenceCategoryrequired

Why an outcome happened, in a closed vocabulary (attempts.category, delivery_events.category).

Allowed:acceptedinvalid_recipientmailbox_fullno_routeinvalid_addresscontent_rejectedpolicythrottledunauthorizedforbiddenconnection_faileddeadlineunsupportedtransientrejecteduncertaindeliveredcomplaintunsubscribedaddress_changedexpiredsuppressedsender_archivedrender_failedworkspace_deleted
confidenceEvidenceConfidencerequired

How much a delivery event can be trusted (delivery_events.confidence).

Allowed:authenticatedcorroboratedinferredhuman_text
diagnosticstring | null
enhanced_statusstring | null
idId_DeliveryEventrequired
matches ^dev_[0-9a-f]{32}$
kindDeliveryEventKindrequired

What kind of observation a delivery event is (delivery_events.kind).

Allowed:accepteddeferreddeliveredbouncedrejectedcomplaintunsubscribedaddress_changedreported
message_idId_Message | null
Show properties
One of:
Id_Message
string
null
null
observed_atTimestamprequired

When the source observed it.

phaseSubmissionPhase | null
Show properties
One of:
SubmissionPhase
SubmissionPhase
null
null
processed_atTimestamprequired

When Norbelys recorded it.

provider_codestring | null

An exact provider-specific rejection code found in diagnostic, when any; it does not change the event's kind, recipient effect, or retry decision.

received_atTimestamprequired

When Norbelys received it.

recipientstring | null

The recipient it concerns; null when the evidence names none.

recipient_refRecipientRefrequired

Why an event's recipient is known (delivery_events.recipient_ref).

Allowed:namedsingle_envelopeunknown
sourceEvidenceSourcerequired

Where a delivery event came from (delivery_events.source).

Allowed:smtpprovider_apiprovider_webhookdsnarfinbound_noticepreflightunsubscribemanualsent_folder
thread_idId_Thread | null
Show properties
One of:
Id_Thread
Id_Thread
null
null
has_morebooleanrequired

More events exist; url lists them all.

urlstringrequired

The delivery event list of this message.

expires_atTimestamp | null
Show properties
One of:
Timestamp
string<date-time>
null
null
fromAddressrequired

An address and its display name.

Show properties
emailstringrequired
namestring | null
holdsHoldObject[]required

One per held recipient: at most the 150 addresses of the envelope.

max items 150
Show properties
Array of HoldObject
emailstringrequired
observed_atTimestamprequired
reasonHoldReasonrequired

Why an address is held (recipient_holds.reason).

Allowed:mailbox_fullgreylistedno_routeinvalid_recipient
resolutionHoldResolution | null
Show properties
One of:
HoldResolution
string
null
null
resolved_atTimestamp | null
Show properties
One of:
Timestamp
string<date-time>
null
null
review_afterTimestamprequired

When the hold is checked again.

idId_Messagerequired
matches ^msg_[0-9a-f]{32}$
in_reply_tostring | null

The Message-ID it answers.

internet_message_idstringrequired

The Message-ID header.

kindMessageKindrequired

What a message is, as messages.kind stores it.

Allowed:campaigndirectreplytransactional
person_idId_Person | null
Show properties
One of:
Id_Person
string
null
null
reply_tostring | null
send_atTimestamprequired

When it is due.

sender_identity_idId_SenderIdentityrequired
matches ^sid_[0-9a-f]{32}$
sent_atTimestamp | null
Show properties
One of:
Timestamp
string<date-time>
null
null
snippets_fallbackSnippetsFallback | null
Show properties
One of:
SnippetsFallback
string
null
null
stateMessageStaterequired

Where a message is in its life, as messages.state stores it. queued, claimed and in_flight are live (the message has a row in the delivery queue); the others are final.

Allowed:queuedclaimedin_flightsentfailedcancelleduncertainsuppressed
status_detailstring | null

Why it is in its state, when that needs words.

step_idId_Step | null
Show properties
One of:
Id_Step
string
null
null
subjectstringrequired

The subject as sent.

thread_idId_Thread | null
Show properties
One of:
Id_Thread
string
null
null
tostring[]required
trackingTrackingrequired

What a message tracks, frozen when it was created.

Show properties
clicksbooleanrequired

Its links lead through click links.

hostnamestring | null

The campaign's own tracking host, when it has one; the platform's otherwise.

opensbooleanrequired

An open pixel is added to its HTML.

updated_atTimestamprequired
variant_idId_Variant | null
Show properties
One of:
Id_Variant
string
null
null
400

No Idempotency-Key, or malformed JSON.

codeProblemCoderequired

The closed registry of problem codes: programs branch on a problem's code, never on its text. A code may be added, never repurposed.

Allowed:invalid_requestunauthorizedforbiddensession_requirednot_foundarchivedmethod_not_allowedconflictinvalid_stateidempotency_in_progressprecondition_failedpayload_too_largeunsupported_media_typevalidation_failedidempotency_mismatchsuppressedcaptcha_failedinsufficient_scoperate_limitedquota_exceededinternal_errorservice_unavailabletimeout
detailstringrequired

What went wrong, for a person; never an internal cause.

errorsFieldError[]

With validation_failed only: every invalid field.

Show properties
Array of FieldError
codestringrequired

What is wrong (required, range, length, format, invalid, …).

detailstringrequired

A safe, human-readable explanation.

pointerstringrequired

RFC 6901 pointer into the body, or ?name for a query parameter.

instancestringrequired

The request's path.

request_idstringrequired

The request's id, also in X-Request-Id: what support needs to find the request.

retry_afterinteger<int64> | null

With 429 and 503: the seconds to wait, as in Retry-After.

min 0
statusinteger<int32>required

The HTTP status.

min 0
titlestringrequired

Fixed per code.

typestringrequired

https://docs.norbelys.com/errors/<code>, a page that explains the code.

401

No valid credential.

codeProblemCoderequired

The closed registry of problem codes: programs branch on a problem's code, never on its text. A code may be added, never repurposed.

Allowed:invalid_requestunauthorizedforbiddensession_requirednot_foundarchivedmethod_not_allowedconflictinvalid_stateidempotency_in_progressprecondition_failedpayload_too_largeunsupported_media_typevalidation_failedidempotency_mismatchsuppressedcaptcha_failedinsufficient_scoperate_limitedquota_exceededinternal_errorservice_unavailabletimeout
detailstringrequired

What went wrong, for a person; never an internal cause.

errorsFieldError[]

With validation_failed only: every invalid field.

Show properties
Array of FieldError
codestringrequired

What is wrong (required, range, length, format, invalid, …).

detailstringrequired

A safe, human-readable explanation.

pointerstringrequired

RFC 6901 pointer into the body, or ?name for a query parameter.

instancestringrequired

The request's path.

request_idstringrequired

The request's id, also in X-Request-Id: what support needs to find the request.

retry_afterinteger<int64> | null

With 429 and 503: the seconds to wait, as in Retry-After.

min 0
statusinteger<int32>required

The HTTP status.

min 0
titlestringrequired

Fixed per code.

typestringrequired

https://docs.norbelys.com/errors/<code>, a page that explains the code.

403

The credential lacks messages:send.

codeProblemCoderequired

The closed registry of problem codes: programs branch on a problem's code, never on its text. A code may be added, never repurposed.

Allowed:invalid_requestunauthorizedforbiddensession_requirednot_foundarchivedmethod_not_allowedconflictinvalid_stateidempotency_in_progressprecondition_failedpayload_too_largeunsupported_media_typevalidation_failedidempotency_mismatchsuppressedcaptcha_failedinsufficient_scoperate_limitedquota_exceededinternal_errorservice_unavailabletimeout
detailstringrequired

What went wrong, for a person; never an internal cause.

errorsFieldError[]

With validation_failed only: every invalid field.

Show properties
Array of FieldError
codestringrequired

What is wrong (required, range, length, format, invalid, …).

detailstringrequired

A safe, human-readable explanation.

pointerstringrequired

RFC 6901 pointer into the body, or ?name for a query parameter.

instancestringrequired

The request's path.

request_idstringrequired

The request's id, also in X-Request-Id: what support needs to find the request.

retry_afterinteger<int64> | null

With 429 and 503: the seconds to wait, as in Retry-After.

min 0
statusinteger<int32>required

The HTTP status.

min 0
titlestringrequired

Fixed per code.

typestringrequired

https://docs.norbelys.com/errors/<code>, a page that explains the code.

404

No such message in this workspace.

codeProblemCoderequired

The closed registry of problem codes: programs branch on a problem's code, never on its text. A code may be added, never repurposed.

Allowed:invalid_requestunauthorizedforbiddensession_requirednot_foundarchivedmethod_not_allowedconflictinvalid_stateidempotency_in_progressprecondition_failedpayload_too_largeunsupported_media_typevalidation_failedidempotency_mismatchsuppressedcaptcha_failedinsufficient_scoperate_limitedquota_exceededinternal_errorservice_unavailabletimeout
detailstringrequired

What went wrong, for a person; never an internal cause.

errorsFieldError[]

With validation_failed only: every invalid field.

Show properties
Array of FieldError
codestringrequired

What is wrong (required, range, length, format, invalid, …).

detailstringrequired

A safe, human-readable explanation.

pointerstringrequired

RFC 6901 pointer into the body, or ?name for a query parameter.

instancestringrequired

The request's path.

request_idstringrequired

The request's id, also in X-Request-Id: what support needs to find the request.

retry_afterinteger<int64> | null

With 429 and 503: the seconds to wait, as in Retry-After.

min 0
statusinteger<int32>required

The HTTP status.

min 0
titlestringrequired

Fixed per code.

typestringrequired

https://docs.norbelys.com/errors/<code>, a page that explains the code.

422

The body is invalid (validation_failed).

codeProblemCoderequired

The closed registry of problem codes: programs branch on a problem's code, never on its text. A code may be added, never repurposed.

Allowed:invalid_requestunauthorizedforbiddensession_requirednot_foundarchivedmethod_not_allowedconflictinvalid_stateidempotency_in_progressprecondition_failedpayload_too_largeunsupported_media_typevalidation_failedidempotency_mismatchsuppressedcaptcha_failedinsufficient_scoperate_limitedquota_exceededinternal_errorservice_unavailabletimeout
detailstringrequired

What went wrong, for a person; never an internal cause.

errorsFieldError[]

With validation_failed only: every invalid field.

Show properties
Array of FieldError
codestringrequired

What is wrong (required, range, length, format, invalid, …).

detailstringrequired

A safe, human-readable explanation.

pointerstringrequired

RFC 6901 pointer into the body, or ?name for a query parameter.

instancestringrequired

The request's path.

request_idstringrequired

The request's id, also in X-Request-Id: what support needs to find the request.

retry_afterinteger<int64> | null

With 429 and 503: the seconds to wait, as in Retry-After.

min 0
statusinteger<int32>required

The HTTP status.

min 0
titlestringrequired

Fixed per code.

typestringrequired

https://docs.norbelys.com/errors/<code>, a page that explains the code.

Try it
Server
Authorization
Parameters
Bodyapplication/json
Request
curl -X POST 'https://api.norbelys.com/v1/messages/msg_0190f8a2b4c87a10b6d2e4f6a8c0e2f4/release_holds' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Idempotency-Key: string' \
  -H 'Content-Type: application/json' \
  -d '{
  "evidence": "The recipient confirmed by phone that their mailbox has room again."
}'
Response
{
  "attempts": {
    "data": [
      {
        "category": "accepted",
        "claimed_at": "2019-08-24T14:15:22Z",
        "connection_id": "con_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
        "diagnostic": "string",
        "enhanced_status": "string",
        "finished_at": "2019-08-24T14:15:22Z",
        "id": "att_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
        "number": 0,
        "outcome": "accepted",
        "phase": "connect",
        "provider_message_id": "string",
        "recipient_count": 0,
        "smtp_code": 0,
        "started_at": "2019-08-24T14:15:22Z"
      }
    ],
    "has_more": true
  },
  "attempts_count": 0,
  "bcc": [
    "string"
  ],
  "campaign_id": "cmp_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
  "cc": [
    "string"
  ],
  "connection_id": "con_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
  "created_at": "2019-08-24T14:15:22Z",
  "enrollment_id": "enr_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
  "events": {
    "data": [
      {
        "action": "failed",
        "attempt_number": 0,
        "category": "accepted",
        "confidence": "authenticated",
        "diagnostic": "string",
        "enhanced_status": "string",
        "id": "dev_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
        "kind": "accepted",
        "message_id": "msg_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
        "observed_at": "2019-08-24T14:15:22Z",
        "phase": "connect",
        "processed_at": "2019-08-24T14:15:22Z",
        "provider_code": "string",
        "received_at": "2019-08-24T14:15:22Z",
        "recipient": "string",
        "recipient_ref": "named",
        "source": "smtp",
        "thread_id": "thr_0190f8a2b4c87a10b6d2e4f6a8c0e2f4"
      }
    ],
    "has_more": true,
    "url": "string"
  },
  "expires_at": "2019-08-24T14:15:22Z",
  "from": {
    "email": "string",
    "name": "string"
  },
  "holds": [
    {
      "email": "string",
      "observed_at": "2019-08-24T14:15:22Z",
      "reason": "mailbox_full",
      "resolution": "delivered",
      "resolved_at": "2019-08-24T14:15:22Z",
      "review_after": "2019-08-24T14:15:22Z"
    }
  ],
  "id": "msg_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
  "in_reply_to": "string",
  "internet_message_id": "string",
  "kind": "campaign",
  "person_id": "per_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
  "reply_to": "string",
  "send_at": "2019-08-24T14:15:22Z",
  "sender_identity_id": "sid_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
  "sent_at": "2019-08-24T14:15:22Z",
  "snippets_fallback": "off",
  "state": "queued",
  "status_detail": "string",
  "step_id": "stp_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
  "subject": "string",
  "thread_id": "thr_0190f8a2b4c87a10b6d2e4f6a8c0e2f4",
  "to": [
    "string"
  ],
  "tracking": {
    "clicks": true,
    "hostname": "string",
    "opens": true
  },
  "updated_at": "2019-08-24T14:15:22Z",
  "variant_id": "var_0190f8a2b4c87a10b6d2e4f6a8c0e2f4"
}