Subscribers

Add a subscriber

Puts an address on this newsletter's list. Needs audience: write, and is a write.

This is not an import, and it is the call a welcome sequence listens for. It publishes subscriber.created, which is the topic automations trigger on, so every address added here enters whatever welcome sequence the newsletter has running. An import and the daily provider sync deliberately publish no such event, so a list migrated in never gets welcomed; calling this in a loop over a list you already have is how you undo that, one email at a time. Move a list with an import.

An address already on the list is not an error. A signup form cannot know whether the person in front of it subscribed last year, so:

  • Already subscribed: nothing changes, nothing is published, and the answer is 200 with the subscriber as it stands.
  • unsubscribed or bounced: the subscription is reactivated and the answer is 200. This publishes subscriber.created with resubscribed: true, which automations treat as not a new subscriber, so nobody is welcomed twice.
  • complained: refused with 422. The reader told a mailbox provider this newsletter is spam, and only the reader can undo that by subscribing again themselves.

A new subscriber answers 201. So the status says whether a subscription was created, and the body says what it now is either way.

The same person is one subscriber however their row is shaped. An address that belongs to a Commune account is attached to that account, so the subscription follows the address on it, and an address Commune has never seen is stored on the subscription itself, lowercased. Two calls differing only in case are therefore one subscriber rather than two copies of one person receiving every article twice.

source comes back commune: the subscription was made on Commune and was not mirrored off a provider's list. tags is empty, because a tag decides what somebody can read and is applied by its own call.

On a newsletter connected to an outside provider this writes Commune's record and not the provider's. Nothing is added to Kit, Mailchimp or anywhere else, so add the contact there too if that list is your source of truth. The daily sync only ever adds, so a subscriber written here is not removed by it.

post/newsletters/{newsletter}/subscribers

Request

  • Base URL: https://api.usecommune.com
  • URL: https://api.usecommune.com/newsletters/{newsletter}/subscribers
  • Auth: one of:
    • HTTP bearer
    • OAuth 2 (authorization code, authorization URL https://usecommune.com/api/oauth/authorize, token URL https://usecommune.com/api/oauth/token, scopes: audience:write)

Headers

Idempotency-Keystring required

A value of your choosing naming the change this request is making.

Send the same value again to retry the same request. Commune replays the answer the first attempt gave instead of making the change twice, and marks the replay with an Idempotent-Replay: true response header. Send a different value for a different change: a key reused for a request that differs in any way answers 409, because replaying an answer to a question you did not ask is a wrong answer you could not detect.

A UUID per change is the usual choice. Remembered for 24 hours, per credential, so two credentials choosing the same value never see each other's answers.

Required, not optional.

Request body

emailstring email required

Where the newsletter should reach this person. Matched case-insensitively against the list and stored lowercased, so two calls differing only in case are one subscriber.

Example request

{
  "email": "new.reader@example.com"
}

Response

The address was already on the list. Reactivated if it was inactive, left alone if it was already subscribed.

object'subscriber' required

Always subscriber.

idstring uuid required

Stable identifier for this membership.

emailstring email required

Where the newsletter reaches this person. Returned on every subscriber, including one with a Commune account behind them.

For a subscriber with no account it is the address they subscribed with. For one with an account it is the address on that account, which is where the article is actually delivered. Never null.

This is the one place in the API an address appears. It is a property of the subscription rather than of the person, so it is never on a public profile, never on an expanded author, and never reachable from a credential granted another newsletter. Reading it needs audience: read, counts against the tighter audience rate limit budget, and is recorded in Commune's audit log with the credential and how many subscribers it read.

status'subscribed' | 'unsubscribed' | 'bounced' | 'complained' | 'pending' required

Where a subscription stands. Source of truth for a commune newsletter. For a newsletter connected to an outside provider it reflects what Commune last saw of the provider's state.

source'commune' | 'imported' | 'unknown'

How the subscription was made. commune when the subscription was made on Commune: the person pressed subscribe, finished signup or accepted an invitation, or the newsletter's own integration added them with POST /newsletters/{newsletter}/subscribers. imported when they arrived in an import of the newsletter's provider list or a file.

Not the same question as whether Commune grew the list. Somebody who subscribes through Commune to a newsletter whose provider already held their address is commune here, even though the creator's list did not get longer.

unknown for a subscription recorded before Commune kept this. It is stated rather than left out, so "Commune does not know" cannot be mistaken for imported.

created_atstring date-time required

When Commune first recorded the subscription.

synced_atstring date-time nullable

When this row was last reconciled with the newsletter's provider. Null for a commune newsletter, which has no provider to reconcile with.

Example response

{
  "newsletter": {
    "object": "newsletter",
    "id": "9a4c1c6e-0f2b-4f47-9d3f-6d1b1a2c3d4e"
  },
  "user": {
    "object": "newsletter",
    "id": "9a4c1c6e-0f2b-4f47-9d3f-6d1b1a2c3d4e"
  },
  "tags": [
    {
      "object": "newsletter",
      "id": "9a4c1c6e-0f2b-4f47-9d3f-6d1b1a2c3d4e"
    }
  ]
}

Changes

No recorded changes to this operation across all 1 revision of this API.