> ## Documentation Index
> Fetch the complete documentation index at: https://www.courier.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Install the Courier skill before writing code: `npx skills add trycourier/courier-skills`. It carries the verified SDK shapes and the rules you cannot get wrong.
> Authenticate every request with `Authorization: Bearer <API_KEY>`. A workspace has several environments and each has its own keys, which are plain `pk_` strings with no environment prefix. Start with Test.
> Send with `client.send.message`, the default import of the v7 Node SDK. Reference a template by its `nt_` id or its alias.
> A send accepts a bare Elemental element list, but storing content on a template requires the top-level elements wrapped in a channel element.
> Templates and journeys can be built in the Courier app or created through the API. Either way they live in the workspace and are referenced by ID when you send.
> The hosted MCP server is https://mcp.courier.com. For a briefing on what Courier is and when to use it, read https://www.courier.com/llms.txt.
> Prefer the Guides tab for how-do-I questions and the Docs tab for how-does-it-behave questions. The API reference lives under /api-reference.

# Send push with Pushbullet through Courier

> Connect Pushbullet with an access token; no profile field is needed.

export const AppLink = ({href, children, name, bare}) => {
  const label = children || name || "Open in Courier";
  if (bare) {
    return <a href={href} target="_blank" rel="noreferrer">{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="app" href={href} target="_blank" rel="noreferrer">
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method" aria-hidden="true">↗</span>
    </a>;
};

export const Doc = ({href, children, name, bare}) => {
  const label = children || name || href;
  if (bare) {
    return <a href={href}>{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="doc" href={href}>
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method">DOC</span>
    </a>;
};

## Prerequisites

* [A Pushbullet account](https://www.pushbullet.com/)
* Your Pushbullet Access Token

## Setup

<Steps>
  <Step title="Create a Pushbullet access token">
    In Pushbullet, open [account settings](https://www.pushbullet.com/#settings/account) and create an access token.
  </Step>

  <Step title="Configure in Courier">
    Open the <AppLink href="https://app.courier.com/integrations/catalog/pushbullet">Pushbullet Integration</AppLink> in Courier, enter your access token, then click "Save."
  </Step>
</Steps>

## Profile requirements

Device tokens live on the user profile rather than on the send, so one profile can hold tokens for several devices and every push provider reads them from the same place. <Doc href="/docs/send/push/overview">Send push</Doc> covers the model.

Pushbullet needs no profile data.

## Overrides

<Doc href="/docs/send/overrides#how-overrides-work">How overrides work</Doc> covers the two levels and which one wins. <Doc href="/docs/integrations/push/overview#channel-overrides">Push channel overrides</Doc> lists the fields every push provider takes.

Overrides change the request body Courier sends. You can override any field supported by Pushbullet's `/pushes` endpoint ([Pushbullet's create push reference](https://docs.pushbullet.com/#create-push)).

### Body overrides

This example sends a `url` by overriding the push `type`:

<CodeGroup>
  ```javascript Node.js highlight={9-10} theme={null}
  const { requestId } = await courier.send.message({
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {},
      providers: {
        pushbullet: {
          override: {
            body: {
              type: "link",
              url: "https://www.courier.com",
            },
          },
        },
      },
    },
  });
  ```

  ```python Python highlight={9-10} theme={null}
  response = client.send.message(
      message={
          "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
          "to": {},
          "providers": {
              "pushbullet": {
                  "override": {
                      "body": {
                          "type": "link",
                          "url": "https://www.courier.com",
                      },
                  },
              },
          },
      },
  )
  ```

  ```bash cURL highlight={1,12-13} wrap theme={null}
  curl -X POST https://api.courier.com/send \
    -H "Authorization: Bearer $COURIER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "message": {
        "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
        "to": {},
        "providers": {
          "pushbullet": {
            "override": {
              "body": {
                "type": "link",
                "url": "https://www.courier.com"
              }
            }
          }
        }
      }
    }'
  ```

  ```ruby Ruby highlight={9-10} theme={null}
  response = courier.send_.message(
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {},
      providers: {
        pushbullet: {
          override: {
            body: {
              type: "link",
              url: "https://www.courier.com"
            }
          }
        }
      }
    }
  )
  ```

  ```go Go highlight={12-13} theme={null}
  response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
  	Message: courier.SendMessageParamsMessage{
  		To: courier.SendMessageParamsMessageToUnion{
  			OfUserRecipient: &shared.UserRecipientParam{
  			},
  		},
  		Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
  		Providers: shared.MessageProvidersParam{
  			"pushbullet": shared.MessageProvidersTypeParam{
  				Override: map[string]any{
  					"body": map[string]any{
  						"type": "link",
  						"url": "https://www.courier.com",
  					},
  				},
  			},
  		},
  	},
  })
  ```

  ```java Java highlight={8-9} theme={null}
  SendMessageParams params = SendMessageParams.builder()
      .message(SendMessageParams.Message.builder()
          .to(UserRecipient.builder().build())
          .template("nt_01kx4h2jdafq8bk9aftxak4b40")
          .providers(MessageProviders.builder()
              .putAdditionalProperty("pushbullet", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
                      "body", java.util.Map.of(
                          "type", "link",
                          "url", "https://www.courier.com"
                      )
                  ))))
              .build())
          .build())
      .build();
  SendMessageResponse response = client.send().message(params);
  ```

  ```php PHP highlight={9-10} theme={null}
  $response = $client->send->message(
    message: [
      'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
      'to' => [],
      'providers' => [
        'pushbullet' => [
          'override' => [
            'body' => [
              'type' => 'link',
              'url' => 'https://www.courier.com',
            ],
          ],
        ],
      ],
    ],
  );
  ```

  ```csharp C# highlight={17-18} theme={null}
  SendMessageParams parameters = new()
  {
      Message = new()
      {
          To = new UserRecipient {  },
          Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
          Providers = new Dictionary<string, MessageProvidersType>()
          {
              {
                  "pushbullet",
                  new()
                  {
                      Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
                          """
                          {
                            "body": {
                              "type": "link",
                              "url": "https://www.courier.com"
                            }
                          }
                          """
                      ),
                  }
              },
          },
      },
  };

  var response = await client.Send.Message(parameters);
  ```

  ```bash CLI highlight={5} wrap theme={null}
  courier send message \
    --api-key "$COURIER_API_KEY" \
    --message.to '{}' \
    --message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
    --message.providers '{"pushbullet": {"override": {"body": {"type": "link", "url": "https://www.courier.com"}}}}'
  ```

  ```text MCP theme={null}
  With Courier MCP, send my template through Pushbullet as a link push.
  ```
</CodeGroup>

### Config overrides

Swap the access token at send time with a config override:

<CodeGroup>
  ```javascript Node.js highlight={6-12} theme={null}
  const { requestId } = await courier.send.message({
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {},
      providers: {
        pushbullet: {
          override: {
            config: {
              accessToken: "RUNTIME_ACCESS_TOKEN",
            },
          },
        },
      },
    },
  });
  ```

  ```python Python highlight={6-12} theme={null}
  response = client.send.message(
      message={
          "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
          "to": {},
          "providers": {
              "pushbullet": {
                  "override": {
                      "config": {
                          "accessToken": "RUNTIME_ACCESS_TOKEN",
                      },
                  },
              },
          },
      },
  )
  ```

  ```bash cURL highlight={9-15} wrap theme={null}
  curl -X POST https://api.courier.com/send \
    -H "Authorization: Bearer $COURIER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "message": {
        "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
        "to": {},
        "providers": {
          "pushbullet": {
            "override": {
              "config": {
                "accessToken": "RUNTIME_ACCESS_TOKEN"
              }
            }
          }
        }
      }
    }'
  ```

  ```ruby Ruby highlight={6-12} theme={null}
  response = courier.send_.message(
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {},
      providers: {
        pushbullet: {
          override: {
            config: {
              accessToken: "RUNTIME_ACCESS_TOKEN"
            }
          }
        }
      }
    }
  )
  ```

  ```go Go highlight={9-15} theme={null}
  response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
  	Message: courier.SendMessageParamsMessage{
  		To: courier.SendMessageParamsMessageToUnion{
  			OfUserRecipient: &shared.UserRecipientParam{
  			},
  		},
  		Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
  		Providers: shared.MessageProvidersParam{
  			"pushbullet": shared.MessageProvidersTypeParam{
  				Override: map[string]any{
  					"config": map[string]any{
  						"accessToken": "RUNTIME_ACCESS_TOKEN",
  					},
  				},
  			},
  		},
  	},
  })
  ```

  ```java Java highlight={6-10} theme={null}
  SendMessageParams params = SendMessageParams.builder()
      .message(SendMessageParams.Message.builder()
          .to(UserRecipient.builder().build())
          .template("nt_01kx4h2jdafq8bk9aftxak4b40")
          .providers(MessageProviders.builder()
              .putAdditionalProperty("pushbullet", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
                      "config", java.util.Map.of(
                          "accessToken", "RUNTIME_ACCESS_TOKEN"
                      )
                  ))))
              .build())
          .build())
      .build();
  SendMessageResponse response = client.send().message(params);
  ```

  ```php PHP highlight={6-12} theme={null}
  $response = $client->send->message(
    message: [
      'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
      'to' => [],
      'providers' => [
        'pushbullet' => [
          'override' => [
            'config' => [
              'accessToken' => 'RUNTIME_ACCESS_TOKEN',
            ],
          ],
        ],
      ],
    ],
  );
  ```

  ```csharp C# highlight={9-23} theme={null}
  SendMessageParams parameters = new()
  {
      Message = new()
      {
          To = new UserRecipient {  },
          Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
          Providers = new Dictionary<string, MessageProvidersType>()
          {
              {
                  "pushbullet",
                  new()
                  {
                      Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
                          """
                          {
                            "config": {
                              "accessToken": "RUNTIME_ACCESS_TOKEN"
                            }
                          }
                          """
                      ),
                  }
              },
          },
      },
  };

  var response = await client.Send.Message(parameters);
  ```

  ```bash CLI highlight={5} wrap theme={null}
  courier send message \
    --api-key "$COURIER_API_KEY" \
    --message.to '{}' \
    --message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
    --message.providers '{"pushbullet": {"override": {"config": {"accessToken": "RUNTIME_ACCESS_TOKEN"}}}}'
  ```

  ```text MCP theme={null}
  With Courier MCP, send my template through Pushbullet with a different access token.
  ```
</CodeGroup>

## Provider details

```text theme={null}
pushbullet
```

Courier recommends routing to the channel. Naming this key in `routing.channels` instead is supported, and sends through just this provider.

<Card title="Send to a specific provider" icon="bullseye-arrow" href="/docs/send/send-to-a-provider" horizontal arrow="true">
  When that is worth doing, and what you give up: failover, channel priority, and providers you add later.
</Card>
