1"use strict";(globalThis.webpackChunk_zyphr_docs=globalThis.webpackChunk_zyphr_docs||[]).push([[1361],{91392(e,n,t){t.r(n),t.d(n,{assets:()=>b,contentTitle:()=>v,default:()=>w,frontMatter:()=>f,metadata:()=>r,toc:()=>k});const r=JSON.parse('{"id":"getting-started/quickstart","title":"Quickstart","description":"Get started with Zyphr in under 5 minutes. Create an account, get your API key, and send your first notification.","source":"@site/docs/getting-started/quickstart.md","sourceDirName":"getting-started","slug":"/getting-started/quickstart","permalink":"/docs/getting-started/quickstart","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"sidebar_position":1,"title":"Quickstart","description":"Get started with Zyphr in under 5 minutes. Create an account, get your API key, and send your first notification."},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/docs/"},"next":{"title":"Quickstart","permalink":"/docs/getting-started/quickstart"}}');var s=t(31085),i=t(71184),a=t(14041),o=t(54357),l=t(57473),d=t(91034),c=t(60841),h=t(90213);const u="tabList_M0Dn",p="tabItem_ysIP";function y({className:e,block:n,selectedValue:t,selectValue:r,tabValues:i}){const a=[],{blockElementScrollPositionUntilNextRender:l}=(0,d.a_)(),c=e=>{const n=e.currentTarget,s=a.indexOf(n),o=i[s].value;o!==t&&(l(n),r(o))},h=e=>{let n=null;switch(e.key){case"Enter":c(e);break;case"ArrowRight":{const t=a.indexOf(e.currentTarget)+1;n=a[t]??a[0];break}case"ArrowLeft":{const t=a.indexOf(e.currentTarget)-1;n=a[t]??a[a.length-1];break}}n?.focus()};return(0,s.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.A)("tabs",{"tabs--block":n},e),children:i.map(({value:e,label:n,attributes:r})=>(0,s.jsx)("li",{role:"tab",tabIndex:t===e?0:-1,"aria-selected":t===e,ref:e=>{a.push(e)},onKeyDown:h,onClick:c,...r,className:(0,o.A)("tabs__item",p,r?.className,{"tabs__item--active":t===e}),children:n??e},e))})}function m({lazy:e,children:n,selectedValue:t}){const r=(Array.isArray(n)?n:[n]).filter(Boolean);if(e){const e=r.find(e=>e.props.value===t);return e?(0,a.cloneElement)(e,{className:(0,o.A)("margin-top--md",e.props.className)}):null}return(0,s.jsx)("div",{className:"margin-top--md",children:r.map((e,n)=>(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==t}))})}function j(e){const n=(0,c.u)(e);return(0,s.jsxs)("div",{className:(0,o.A)(l.G.tabs.container,"tabs-container",u),children:[(0,s.jsx)(y,{...n,...e}),(0,s.jsx)(m,{...n,...e})]})}function x(e){const n=(0,h.default)();return(0,s.jsx)(j,{...e,children:(0,c.v)(e.children)},String(n))}var g=t(53759);const f={sidebar_position:1,title:"Quickstart",description:"Get started with Zyphr in under 5 minutes. Create an account, get your API key, and send your first notification."},v="Quickstart",b={},k=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Step 1: Create an Account",id:"step-1-create-an-account",level:2},{value:"Step 2: Get Your API Key",id:"step-2-get-your-api-key",level:2},{value:"Step 3: Send Your First Email",id:"step-3-send-your-first-email",level:2},{value:"Send a test email before verifying a domain",id:"send-a-test-email-before-verifying-a-domain",level:2},{value:"Step 4: Verify Domain (for Production)",id:"step-4-verify-domain-for-production",level:2},{value:"Step 5: Go Live",id:"step-5-go-live",level:2},{value:"Next Steps",id:"next-steps",level:2}];function _(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"quickstart",children:"Quickstart"})}),"\n",(0,s.jsx)(n.p,{children:"This guide will walk you through sending your first notification with Zyphr in under 5 minutes."}),"\n",(0,s.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["A Zyphr account (",(0,s.jsx)(n.a,{href:"https://app.zyphr.dev/signup",children:"Sign up free"}),")"]}),"\n",(0,s.jsx)(n.li,{children:"An API key (created in the Dashboard)"}),"\n"]}),"\n",(0,s.jsx)(n.admonition,{title:"Using an AI coding editor?",type:"tip",children:(0,s.jsxs)(n.p,{children:["Skip the SDK install and code snippets \u2014 drop the ",(0,s.jsx)(n.a,{href:"/sdks/mcp-server",children:"Zyphr MCP Server"}),' into Claude Code, Cursor, Cline, or any MCP-compatible client. Once it\'s connected, ask the AI "add Zyphr email to this project" and it will wire up the install, the client, the route, and even the webhook signature verification for you.']})}),"\n",(0,s.jsx)(n.h2,{id:"step-1-create-an-account",children:"Step 1: Create an Account"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Go to ",(0,s.jsx)(n.a,{href:"https://app.zyphr.dev/signup",children:"app.zyphr.dev/signup"})]}),"\n",(0,s.jsx)(n.li,{children:"Create your account with email/password or OAuth"}),"\n",(0,s.jsxs)(n.li,{children:["An ",(0,s.jsx)(n.strong,{children:"account"})," and a ",(0,s.jsx)(n.strong,{children:"Default project"})," are created automatically \u2014 you are ready to go"]}),"\n"]}),"\n",(0,s.jsx)(n.admonition,{title:"Accounts & Projects",type:"info",children:(0,s.jsxs)(n.p,{children:["Your ",(0,s.jsx)(n.strong,{children:"account"})," is your organization \u2014 it owns billing, team members, and projects. A ",(0,s.jsx)(n.strong,{children:"project"})," is an isolated environment with its own API keys, domains, subscribers, and messages. You can create additional projects later (e.g., Production, Staging, Development). See ",(0,s.jsx)(n.a,{href:"/guides/projects",children:"Accounts & Projects"})," for details."]})}),"\n",(0,s.jsx)(n.h2,{id:"step-2-get-your-api-key",children:"Step 2: Get Your API Key"}),"\n",(0,s.jsx)(n.p,{children:"All resources \u2014 including API keys \u2014 are created within your current project. Make sure you are in the correct project before proceeding (use the project switcher in the header)."}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Navigate to ",(0,s.jsx)(n.strong,{children:"Settings"})," > ",(0,s.jsx)(n.strong,{children:"API Keys"})," in the dashboard"]}),"\n",(0,s.jsxs)(n.li,{children:["Click ",(0,s.jsx)(n.strong,{children:"Create API Key"})]}),"\n",(0,s.jsx)(n.li,{children:'Give it a name (e.g., "Development")'}),"\n",(0,s.jsx)(n.li,{children:"Copy your API key \u2014 you will only see it once!"}),"\n"]}),"\n",(0,s.jsxs)(n.admonition,{title:"Test keys are being retired",type:"warning",children:[(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"zy_test_*"})," keys are ",(0,s.jsx)(n.strong,{children:"no longer issued"}
1),", and existing ones stop working on\n",(0,s.jsx)(n.strong,{children:"21 October 2026"}),". They never delivered mail \u2014 sends were mocked and marked\nsent without reaching a provider, so they could not verify domain\nauthentication, template rendering, or deliverability."]}),(0,s.jsxs)(n.p,{children:["To test your integration, use a ",(0,s.jsx)(n.code,{children:"zy_live_*"})," key against a verified domain and\nsend to an address you control. That exercises the real delivery path."]})]}),"\n",(0,s.jsx)(n.h2,{id:"step-3-send-your-first-email",children:"Step 3: Send Your First Email"}),"\n","\n",(0,s.jsxs)(x,{groupId:"language",children:[(0,s.jsx)(g.default,{value:"curl",label:"cURL",default:!0,children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'curl -X POST https://api.zyphr.dev/v1/emails \\\n -H "X-API-Key: zy_test_your_api_key" \\\n -H "Content-Type: application/json" \\\n -d \'{\n "to": "[email protected]",\n "subject": "Hello from Zyphr!",\n "html": "<h1>It works!</h1><p>You just sent your first email with Zyphr.</p>"\n }\'\n'})})}),(0,s.jsx)(g.default,{value:"node",label:"Node.js",children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"import { Configuration, EmailsApi } from '@zyphr-dev/node-sdk';\n\nconst config = new Configuration({ apiKey: 'zy_test_your_api_key' });\nconst emails = new EmailsApi(config);\n\nconst result = await emails.sendEmail({\n sendEmailRequest: {\n to: '[email protected]',\n subject: 'Hello from Zyphr!',\n html: '<h1>It works!</h1><p>You just sent your first email with Zyphr.</p>',\n },\n});\n\nconsole.log(`Email sent: ${result.id}`);\n"})})}),(0,s.jsx)(g.default,{value:"python",label:"Python",children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:'import requests\n\nresponse = requests.post(\n "https://api.zyphr.dev/v1/emails",\n headers={\n "X-API-Key": "zy_test_your_api_key",\n "Content-Type": "application/json",\n },\n json={\n "to": "[email protected]",\n "subject": "Hello from Zyphr!",\n "html": "<h1>It works!</h1><p>You just sent your first email with Zyphr.</p>",\n },\n)\n\ndata = response.json()\nprint(f"Email sent: {data[\'data\'][\'id\']}")\n'})})}),(0,s.jsx)(g.default,{value:"go",label:"Go",children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-go",children:'package main\n\nimport (\n "bytes"\n "encoding/json"\n "fmt"\n "net/http"\n)\n\nfunc main() {\n body, _ := json.Marshal(map[string]string{\n "to": "[email protected]",\n "subject": "Hello from Zyphr!",\n "html": "<h1>It works!</h1><p>You just sent your first email with Zyphr.</p>",\n })\n\n req, _ := http.NewRequest("POST", "https://api.zyphr.dev/v1/emails", bytes.NewBuffer(body))\n req.Header.Set("X-API-Key", "zy_test_your_api_key")\n req.Header.Set("Content-Type", "application/json")\n\n resp, err := http.DefaultClient.Do(req)\n if err != nil {\n panic(err)\n }\n defer resp.Body.Close()\n\n fmt.Printf("Status: %d\\n", resp.StatusCode)\n}\n'})})}),(0,s.jsx)(g.default,{value:"php",label:"PHP",children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-php",children:"<?php\n\n$ch = curl_init('https://api.zyphr.dev/v1/emails');\n\ncurl_setopt_array($ch, [\n CURLOPT_POST => true,\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_HTTPHEADER => [\n 'X-API-Key: zy_test_your_api_key',\n 'Content-Type: application/json',\n ],\n CURLOPT_POSTFIELDS => json_encode([\n 'to' => '[email protected]',\n 'subject' => 'Hello from Zyphr!',\n 'html' => '<h1>It works!</h1><p>You just sent your first email with Zyphr.</p>',\n ]),\n]);\n\n$response = curl_exec($ch);\n$data = json_decode($response, true);\necho \"Email sent: \" . $data['data']['id'] . \"\\n\";\n\ncurl_close($ch);\n"})})}),(0,s.jsx)(g.default,{value:"ruby",label:"Ruby",children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:"require 'net/
1http'\nrequire 'json'\nrequire 'uri'\n\nuri = URI('https://api.zyphr.dev/v1/emails')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(uri)\nrequest['X-API-Key'] = 'zy_test_your_api_key'\nrequest['Content-Type'] = 'application/json'\nrequest.body = {\n to: '[email protected]',\n subject: 'Hello from Zyphr!',\n html: '<h1>It works!</h1><p>You just sent your first email with Zyphr.</p>'\n}.to_json\n\nresponse = http.request(request)\ndata = JSON.parse(response.body)\nputs \"Email sent: #{data['data']['id']}\"\n"})})})]}),"\n",(0,s.jsx)(n.p,{children:"Response:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "data": {\n "id": "msg_abc123",\n "to": "[email protected]",\n "subject": "Hello from Zyphr!",\n "status": "queued",\n "is_test": true,\n "created_at": "2024-01-15T10:30:00Z"\n },\n "meta": {\n "request_id": "req_xyz789"\n }\n}\n'})}),"\n",(0,s.jsx)(n.h2,{id:"send-a-test-email-before-verifying-a-domain",children:"Send a test email before verifying a domain"}),"\n",(0,s.jsxs)(n.p,{children:["You don't have to verify a domain just to see Zyphr work. From the dashboard, the\n",(0,s.jsx)(n.strong,{children:"Send test email"})," card delivers a real email to your own verified account address,\nsent from an isolated Zyphr sandbox sender \u2014 no domain setup required. It's the\nfastest way to confirm your account is live before you wire up production sending."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["The recipient is always ",(0,s.jsx)(n.strong,{children:"your own"})," signed-in, email-verified account address \u2014 you\ncan't send a sandbox test to anyone else."]}),"\n",(0,s.jsxs)(n.li,{children:["It's a dashboard onboarding aid (available with your dashboard session), limited to a\nfew sends per day. For sending to real recipients, verify a domain and use the\n",(0,s.jsx)(n.a,{href:"/docs/channels/email",children:"Emails API"})," with an API key."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"step-4-verify-domain-for-production",children:"Step 4: Verify Domain (for Production)"}),"\n",(0,s.jsx)(n.p,{children:"Before sending production emails to real recipients, you need to verify your domain:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Go to ",(0,s.jsx)(n.strong,{children:"Settings"})," \u2192 ",(0,s.jsx)(n.strong,{children:"Domains"})]}),"\n",(0,s.jsxs)(n.li,{children:["Click ",(0,s.jsx)(n.strong,{children:"Add Domain"})]}),"\n",(0,s.jsxs)(n.li,{children:["Enter your domain (e.g., ",(0,s.jsx)(n.code,{children:"notifications.yourapp.com"}),")"]}),"\n",(0,s.jsx)(n.li,{children:"Add the DNS records shown to your DNS provider"}),"\n",(0,s.jsxs)(n.li,{children:["Click ",(0,s.jsx)(n.strong,{children:"Verify"})," once records are propagated"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"step-5-go-live",children:"Step 5: Go Live"}),"\n",(0,s.jsx)(n.p,{children:"Once your domain is verified, swap your test key for a live key:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'curl -X POST https://api.zyphr.dev/v1/emails \\\n -H "X-API-Key: zy_live_your_api_key" \\\n -H "Content-Type: application/json" \\\n -d \'{\n "to": "[email protected]",\n "from": "[email protected]",\n "subject": "Welcome!",\n "html": "<h1>Welcome to our app!</h1>"\n }\'\n'})}),"\n",(0,s.jsx)(n.h2,{id:"next-steps",children:"Next Steps"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/getting-started/authentication",children:"Learn about Authentication"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/getting-started/test-mode",children:"Explore Test Mode"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/channels/push-notifications",children:"Send Push Notifications"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/api/introduction",children:"Browse the API Reference"})}),"\n"]})]})}function w(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(_,{...e})}):_(e)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.