Brevo API: 실무 중심 개발자 가이드
개발자를 위한 Brevo API 가이드. 인증, 기본 URL, 연락처, 트랜잭션 이메일, 캠페인, CRM 객체, 웹훅, 요청 제한, 그리고 실제 운영에서 부딪히는 한계를 다룹니다.
Brevo는 트랜잭션 메시징, 마케팅 캠페인, 연락처 데이터, CRM 레코드를 아우르는 하나의 REST API를 제공합니다. 첫 요청에서 201을 받기까지는 약 2분이면 충분합니다. 하지만 데이터를 조용히 잃지 않는 프로덕션 연동을 만드는 데는 훨씬 더 오래 걸립니다. 가장 중요한 제약 중 상당수가 문서화되어 있지 않거나, API가 스스로 보고하는 내용과 어긋나기 때문입니다.
이 가이드는 두 가지를 모두 다룹니다. 첫날 필요한 엔드포인트, SDK, 인증과 함께, 출시 전에 미리 설계에 반영해야 할 플랫폼 한계를 함께 설명합니다.
Brevo API가 다루는 범위
모든 것이 하나의 호스트와 하나의 버전 경로 아래에 있습니다. 개발자 문서는 이 인터페이스를 네 개의 제품 영역으로 묶습니다.
- 메시징: 트랜잭션 이메일, SMS, WhatsApp. 일괄 발송, 예약 발송, 메시지 활동 내역을 포함합니다.
- 마케팅 플랫폼: 연락처, 리스트, 세그먼트, 이메일 캠페인.
- eCommerce: 상품, 주문, 고객 이벤트 추적.
- Conversations: 채팅 위젯과 프로그래밍 방식의 대화 관리.
이 영역들은 하나의 계정, 하나의 연락처 데이터베이스, 하나의 API 키를 공유합니다. 편리하지만 때로는 위험합니다. 스테이징 데이터를 가정하고 작성한 스크립트가 실제 캠페인을 발송하는 바로 그 연락처를 건드리기 때문입니다.
트랜잭션과 마케팅의 차이
두 계열은 충분히 다르게 동작하며, 이 둘을 혼동하는 것이 가장 흔한 설계 오류입니다.
| 트랜잭션 | 마케팅 | |
|---|---|---|
| 주요 엔드포인트 | POST /v3/smtp/email | POST /v3/emailCampaigns |
| 수신자 지정 | 요청에 수신자를 명시 | listIds 또는 segmentIds |
| 트리거 | 애플리케이션에서 실시간으로 | 예약 발송 또는 수동 발송 |
| 일반적인 볼륨 형태 | 지속적으로 한 통씩 | 한 번에 몰리는 대량 발송 |
| 요청 제한 여력 | 매우 높음, 표준 요금제에서 초당 1,000회 | 낮음, 캠페인 엔드포인트는 일반 상한 적용 |
Brevo가 애초에 적합한 플랫폼인지 아직 판단 중이라면, 플랫폼 개요가 그 부분을 다룹니다.
인증과 키 관리
Brevo는 커스텀 헤더에 담긴 단순한 API 키를 사용합니다. 헤더 이름은 Authorization이 아니라 api-key이며, Bearer 접두사도 없습니다. 다른 메시징 API를 먼저 써 본 사람이라면 거의 예외 없이 여기서 걸립니다.
curl https://api.brevo.com/v3/account \ -H "api-key: $BREVO_API_KEY"키는 Brevo 앱의 계정 설정에서 SMTP and API 섹션의 API keys 탭에서 생성합니다. 각 키에는 그 키를 사용하는 시스템과 연결되는 설명적인 이름을 붙이시기 바랍니다. 키 값은 생성 시점에 정확히 한 번만 표시되므로, 분실하면 기존 키를 복구하는 대신 새 키를 생성해야 합니다.
몇 가지 실무 원칙이 있습니다.
- 배포 대상별, 서비스별로 키를 분리해서 발급하십시오. 유출된 키 하나를 폐기하는 일이 서로 무관한 세 개의 시스템을 중단시켜서는 안 됩니다.
- 표준 API 키는 계정 전체 권한을 가집니다. 모든 키를 연락처, 발송, CRM 데이터에 대한 완전한 접근 권한으로 취급하십시오.
- Brevo는 다른 Brevo 계정을 대신해 동작하는 애플리케이션을 위한 OAuth 2.0도 지원하며, 인증 방식 문서에 키 방식과 함께 설명되어 있습니다.
- AI 어시스턴트가 사용하는 MCP 서버는 별도의 토큰을 사용하며 bearer 헤더를 씁니다. 이 토큰은 같은 API keys 화면에서 생성하지만 REST 키와 서로 바꿔 쓸 수 없습니다.
기본 URL, 버전, 첫 쓰기 요청
기본 URL은 https://api.brevo.com/v3/ 입니다. 버전은 헤더가 아니라 경로에 들어가며, 현재 세대는 v3입니다. 이 가이드의 모든 경로는 이 기본 URL을 기준으로 합니다.
첫 요청은 읽기보다 쓰기가 더 유익합니다. 보통 잘못 설정되어 있는 부분, 특히 인증된 발신자를 실제로 검증하기 때문입니다.
curl -X POST https://api.brevo.com/v3/smtp/email \ -H "api-key: $BREVO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "sender": { "name": "Ops", "email": "[email protected]" }, "to": [{ "email": "[email protected]", "name": "Dev" }], "subject": "First transactional send", "htmlContent": "<html><body><p>It works.</p></body></html>", "tags": ["smoke-test"] }'발송에 성공하면 messageId와 함께 201이 반환됩니다. 예약 발송은 202를 반환합니다.
실제로 사용하게 될 엔드포인트
연락처
POST /v3/contacts 는 연락처를 생성합니다. 본문은 email, 커스텀 필드를 담는 attributes 맵, listIds, 자체 외부 키를 위한 ext_id를 받습니다. 실무에서 가장 중요한 두 플래그는 호출을 업서트로 바꾸는 updateEnabled와 응답에 연락처 ID를 반환하게 하는 getId입니다.
읽기는 GET /v3/contacts 로 처리하며, limit(기본값 50, 최대 1000)과 offset으로 페이지를 나누고 UTC 기준의 modifiedSince, createdSince를 지원합니다. 증분 동기화는 전체 리스트를 훑는 대신 modifiedSince에 의존해야 합니다. filter 파라미터는 동등 비교 연산자만 지원하므로, 그보다 표현력이 필요한 조건은 세그먼트로 옮기시기 바랍니다.
대량 적재에는 POST /v3/contacts/import 를 사용합니다. fileUrl, fileBody, jsonBody를 받고 listIds를 대상으로 하며 비동기로 실행되어 processId를 반환합니다. Brevo는 본문 최대 10 MB를 문서화하고 있으며, 파싱 과정에서 페이로드가 부풀기 때문에 8 MB 근처를 유지하도록 권장합니다. 결과를 폴링하지 않고 통보받으려면 notifyUrl을 지정하십시오.
트랜잭션 이메일
POST /v3/smtp/email 이 핵심입니다. sender, to, subject, htmlContent 외에 알아 둘 만한 필드는 다음과 같습니다.
templateId와params. 인라인 콘텐츠 대신 Brevo 템플릿과 변수 치환을 사용합니다. 개별 버전 파라미터는 100 KB, 누적 파라미터는 1000 KB로 제한됩니다.messageVersions. 한 번의 호출로 개인화된 변형을 발송하며, 버전당 최대 99명의 수신자를 지원합니다.tags. 항상 설정하시기 바랍니다. 태그는 웹훅 이벤트에 함께 돌아오며, 배달 이벤트와 그것을 만든 코드 경로를 연결할 수 있는 유일하게 저렴한 수단입니다.scheduledAt과batchId. 나중에 그룹 단위로 취소할 수도 있는 예약 발송에 사용합니다.headers. 커스텀 SMTP 헤더를 Title-Case로 지정합니다.
한 요청은 최대 2,000명의 수신자를 받습니다. 이 엔드포인트와 캠페인 발송의 차이는 트랜잭션 이메일 가이드에서 메시징 전략 관점으로 다룹니다.
이메일 캠페인
POST /v3/emailCampaigns 는 name과 sender를 요구하며, 여기에 정확히 하나의 콘텐츠 소스가 필요합니다. htmlContent(최소 10자, 1 MB 미만), htmlUrl, templateId 중 하나입니다. 대상은 recipients 안에 listIds 또는 segmentIds로 넣고, scheduledAt은 YYYY-MM-DDTHH:mm:ss.SSSZ UTC 형식을 사용합니다. 즉시 발송, 테스트 발송, 상태 변경, 캠페인 리포트 조회는 별도의 관련 경로가 담당합니다.
회사, 거래, 객체
Brevo CRM에는 겹치는 쓰기 경로가 두 가지 있으며, 어느 쪽을 고르느냐가 중요합니다.
CRM 경로는 POST /v3/companies, PATCH /v3/companies/{id}, DELETE /v3/companies/{id} 와 거래에 대한 동일한 세트입니다. 이들은 동기 방식입니다. PATCH 는 변경이 적용되면 204를 반환합니다.
객체 API는 대량 처리 경로입니다. POST /v3/objects/{object_type}/batch/upsert 는 요청당 최대 1000개 레코드와 1 MB, 레코드당 최대 500개 속성, 레코드당 객체 타입별 최대 10개의 연관 레코드를 받습니다. 반환값은 processId와 함께 202이며, 이는 적용이 아니라 접수를 뜻합니다.
curl -X POST https://api.brevo.com/v3/objects/company/batch/upsert \ -H "api-key: $BREVO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "records": [ { "identifiers": { "id": 12345 }, "attributes": { "domain": "acme.example", "industry": "retail" } } ] }'Brevo CRM 가이드는 같은 객체 모델을 운영자 관점에서 설명합니다.
공식 SDK
Brevo는 getbrevo GitHub 조직에서 클라이언트를 관리합니다.
| 언어 | 저장소 |
|---|---|
| Node.js | github.com/getbrevo/brevo-node |
| Python | github.com/getbrevo/brevo-python |
| PHP | github.com/getbrevo/brevo-php |
| Java | github.com/getbrevo/brevo-java |
| C# | github.com/getbrevo/brevo-csharp |
| Go | github.com/getbrevo/brevo-go |
| Ruby | github.com/getbrevo/brevo-ruby |
Node 클라이언트는 @getbrevo/brevo로 설치합니다.
npm install @getbrevo/brevoimport { BrevoClient } from "@getbrevo/brevo";
const brevo = new BrevoClient({ apiKey: process.env.BREVO_API_KEY });
const result = await brevo.transactionalEmails.sendTransacEmail({ subject: "Order confirmed", htmlContent: "<html><body><p>Thanks for your order.</p></body></html>", tags: ["order-confirmation"],});
console.log("Message ID:", result.messageId);Python 클라이언트는 pip install brevo-python 으로 설치합니다. 엔드포인트 두 개 때문에 SDK 의존성을 끌어안고 싶지 않다면, 원시 HTTP 인터페이스는 직접 호출해도 될 만큼 작습니다. SDK 버전 변경의 영향에서도 자유로워집니다.
import osimport requests
BASE = "https://api.brevo.com/v3"HEADERS = { "api-key": os.environ["BREVO_API_KEY"], "Content-Type": "application/json",}
def upsert_contact(email, attributes, list_ids): response = requests.post( f"{BASE}/contacts", headers=HEADERS, json={ "email": email, "attributes": attributes, "listIds": list_ids, "updateEnabled": True, }, timeout=30, ) response.raise_for_status() return responseAI 어시스턴트를 위한 MCP 서버도 https://mcp.brevo.com/v1/brevo/mcp 에 있으며, 같은 설정 화면에서 생성한 bearer 토큰으로 인증합니다. 탐색이나 계정 관련 질문에는 유용하지만, 프로덕션 데이터 경로에는 적합하지 않습니다.
웹훅
웹훅은 발송 이후에 무슨 일이 일어났는지 알 수 있는 수단입니다. POST /v3/webhooks 로 생성하며, url, events, type과 선택적으로 channel(email 또는 sms), batched, 커스텀 headers, auth 객체를 지정합니다.
웹훅 타입은 세 가지이며 각각 이벤트 어휘가 다릅니다.
- 트랜잭션:
sent,request,delivered,hardBounce,softBounce,blocked,spam,invalid,deferred,click,opened,uniqueOpened,unsubscribed. - 마케팅:
spam,opened,click,hardBounce,softBounce,unsubscribed,listAddition,delivered,contactUpdated,contactDeleted. - 인바운드:
inboundEmailProcessed와reply. 여기에는domain이 추가로 필요합니다.
curl -X POST https://api.brevo.com/v3/webhooks \ -H "api-key: $BREVO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://yourapp.example/hooks/brevo", "type": "transactional", "events": ["delivered", "hardBounce", "spam", "unsubscribed"], "description": "Deliverability signals" }'제대로 챙겨야 할 것이 세 가지 있습니다. 첫째, 한 계정은 모든 타입을 합쳐 최대 40개의 웹훅만 보유할 수 있으므로, 이벤트마다 엔드포인트를 등록하지 말고 핸들러 내부에서 이벤트별로 분기하십시오. 둘째, 볼륨이 예상된다면 batched 플래그를 사용하십시오. 여러 이벤트를 담은 요청 하나가 여러 개의 요청보다 처리 비용이 훨씬 낮습니다. 셋째, 수신 측을 보호하십시오. Brevo는 발신 IP 대역을 공개하고 있으며, 엔드포인트를 해당 대역으로 제한하는 것이 문서화된 방식입니다. 여기에 headers 필드로 자체 공유 시크릿을 추가해 두 번째 방어선을 두십시오.
핸들러는 멱등해야 합니다. 메시지 ID와 이벤트 타입, 타임스탬프의 조합을 중복 제거 키로 사용하시기 바랍니다.
요청 제한과 오류 처리
Brevo의 요청 제한은 엔드포인트별, 요금제 등급별로 정해지며 엔드포인트 사이의 편차가 매우 큽니다.
| 엔드포인트 | 표준 | Professional 및 Enterprise |
|---|---|---|
POST /v3/smtp/email | 초당 1,000회 | 초당 2,000회 |
POST /v3/transactionalSMS/send | 초당 150회 | 초당 200회 |
/v3/contacts/... | 초당 10회, 시간당 36,000회 | 초당 20회, 시간당 72,000회 |
POST /v3/events | 초당 10회, 시간당 36,000회 | Enterprise에서 상향 |
GET /v3/smtp/emails | 초당 2회, 시간당 7,200회 | 초당 3회, 시간당 10,800회 |
| 그 밖의 모든 것 | 시간당 100회 | 시간당 200회 |
문제가 되는 것은 마지막 행입니다. 발송은 사실상 무제한인 반면, 캠페인 관리와 CRM 조회, 대부분의 관리 호출은 표준 요금제에서 시간당 100회라는 예산을 함께 나눠 씁니다. 쓰기 전에 회사 레코드를 읽는 단순한 백필 작업은 2분도 안 되어 한 시간 치 할당량을 소진합니다.
모든 응답에는 x-sib-ratelimit-limit, x-sib-ratelimit-remaining, x-sib-ratelimit-reset 이 담깁니다. 실패했을 때만이 아니라 성공했을 때도 읽으십시오. 제한을 초과하면 429가 반환되며, 올바른 대응은 reset 헤더가 알려 주는 간격만큼 기다린 뒤 지터를 섞은 지수 백오프를 적용하는 것입니다.
async function callBrevo(path, init, attempt = 0) { const response = await fetch(`https://api.brevo.com/v3${path}`, { ...init, headers: { "api-key": process.env.BREVO_API_KEY, "Content-Type": "application/json", ...init.headers }, });
if (response.status === 429 && attempt < 5) { const reset = Number(response.headers.get("x-sib-ratelimit-reset") || 1); const backoff = Math.pow(2, attempt) * 250 + Math.random() * 250; await new Promise((r) => setTimeout(r, reset * 1000 + backoff)); return callBrevo(path, init, attempt + 1); }
return response;}429와 5xx는 재시도하십시오. 400이나 409는 무턱대고 재시도해서는 안 됩니다. 둘 다 요청이 이른 것이 아니라 잘못되었다는 뜻이며, 특히 409는 반복이 아니라 다른 조치를 요구합니다.
메일을 보내지 않고 테스트하기
트랜잭션 발송 요청에 X-Sib-Sandbox 헤더를 drop 값으로 추가하십시오. Brevo는 요청을 검증하고 messageId와 함께 201을 반환하지만 아무것도 배달하지 않고 이메일 로그도 남기지 않습니다.
curl -X POST https://api.brevo.com/v3/smtp/email \ -H "api-key: $BREVO_API_KEY" \ -H "X-Sib-Sandbox: drop" \ -H "Content-Type: application/json" \ -d '{ "sender": { "email": "[email protected]" }, "to": [{ "email": "[email protected]" }], "subject": "Sandbox", "htmlContent": "<p>hi</p>" }'이 기능이 무엇을 증명하고 무엇을 증명하지 않는지 이해하는 것이 중요합니다. 샌드박스 모드는 요청 형식만 검증합니다. 발신자 인증, 템플릿 렌더링, 도달률에 대해서는 아무것도 말해 주지 않습니다. 연락처나 CRM 데이터를 건드리는 모든 것을 테스트하려면 별도의 Brevo 계정을 두시기 바랍니다. 샌드박스 모드는 발송만 다루고 나머지 API는 다루지 않기 때문입니다.
연동 설계를 좌우하는 한계들
다음은 실제 계정에서 일정 규모 이상으로 연동을 운영해 봐야 드러나는 제약입니다. 여러 항목이 API가 스스로 말하는 내용과 어긋납니다. 어느 것도 협상 가능하지 않으므로, 합리적인 대응은 이를 전제로 설계하는 것뿐입니다.
회사에는 도메인이 필요하고, 도메인당 회사는 하나뿐입니다
GET /v3/crm/attributes/companies 는 모든 속성을 필수가 아닌 것으로 보고하고, 회사 생성 레퍼런스는 name만 필수로 표시합니다. 그러나 실제로는 비어 있지 않은 domain 속성 없이 POST /v3/companies 를 호출하면 필수 기본 속성 누락 메시지와 함께 400이 반환됩니다. 빈 문자열도 생략과 똑같이 실패합니다.
더 나쁜 것은 도메인 고유성이 강제된다는 점입니다. 이미 사용 중인 도메인으로 두 번째 회사를 만들면 409가 반환됩니다. B2B 커머스에서 이는 구조적인 문제입니다. 구매자 이메일 도메인 하나를 공유하는 자회사들을 Brevo에서 각각 별도 회사로 존재시킬 수 없습니다. 게다가 연락처를 동기화하는 것만으로도 해당 연락처의 이메일 도메인으로 회사가 생성될 수 있어서, 아무도 명시적으로 만들지 않은 회사와 충돌이 날 수도 있습니다. 올바른 핸들러는 409를 만나면 실패하거나 재시도하지 않고 기존 회사를 채택합니다.
선언되지 않은 속성은 조용히 버려집니다
이것이 플랫폼에서 가장 위험한 동작이며, Brevo도 문서에 명확히 적어 두었습니다. 요청에 포함된 속성이 객체 스키마에 미리 정의되어 있지 않으면 아무 일도 일어나지 않습니다. 오류도, 속성 생성도, 경고도 없습니다.
따라서 2xx 응답은 데이터가 실제로 저장되었다는 증거가 아닙니다. 쓰기 전에 스키마를 읽고, 선언되지 않은 항목은 자체 클라이언트에서 걸러내고, 속성이 존재하지 않는 동기화는 아예 실행을 거부하십시오. 한 달 동안 반쪽짜리 레코드를 쓰다가 뒤늦게 발견하는 것보다 낫습니다.
속성 필터는 받아들여지지만 무시됩니다
GET /v3/companies?filters[attributes.domain]=... 는 200을 반환하고 필터는 무시합니다. 완전히 다른 두 필터가 같은 레코드를 반환합니다. 이 경로로 속성을 기준 삼아 회사를 조회할 방법은 없습니다.
여기에 더해 필터 없는 목록 조회는 대형 계정에서 어떤 페이지 크기로도 504로 타임아웃되기 때문에, 이미 존재하는 회사를 문서화된 경로로는 사실상 찾을 수 없는 상황이 생깁니다. 우회 방법은 GET /v3/objects/company/records 를 sort=desc 로 스캔하는 것입니다. 빠르고 페이지 처리가 되며 속성도 반환되므로, 적당한 페이지 수로 범위를 제한해 사용하면 됩니다. 방금 409를 유발한 회사는 거의 항상 조금 전에 생성된 것이므로, 최신순 스캔으로 금방 찾을 수 있습니다.
객체 타입당 100만 레코드, 그리고 일괄 삭제 부재
POST /v3/objects/{type}/batch/upsert 는 객체 타입이 100만 레코드에 도달하면 400을 반환합니다. 생성뿐 아니라 수정도 막힙니다. 기존 레코드를 자체 숫자 ID로 지정해도 똑같이 실패합니다. 객체 쓰기 경로 전체가 한꺼번에 닫힙니다.
상한 아래로 되돌리는 일은 느립니다. POST /v3/objects/{type}/batch/delete 가 company 같은 Brevo 표준 객체 타입에는 403을 반환하기 때문입니다. 남는 경로는 DELETE /v3/companies/{id} 뿐이며, 호출당 레코드 하나에 대략 156 ms가 걸립니다. 이 방식으로 124,000개 레코드를 지우는 데 워커 20개를 병렬로 돌리고도 몇 시간이 걸렸습니다. 동기화 실패로 상한을 발견하지 말고 레코드 수를 주기적으로 모니터링하시고, 대량 수정은 그런 제한이 없는 PATCH /v3/companies/{id} 로 보내십시오.
ext_id는 사용자의 ID가 아니라 Brevo의 ID입니다
객체 레코드에서 identifiers.ext_id 는 Brevo 자체의 CRM 회사 ID, 즉 Mongo 형식의 문자열을 담습니다. 자유롭게 쓸 수 있는 외부 키가 아닙니다. ext_id 에 자사 플랫폼 식별자를 넣어 업서트를 시도하면 매칭이 아니라 중복 생성이 일어납니다. 외부 ID는 별도로 선언한 속성에 넣어야 합니다.
객체 업서트는 비동기, CRM 쓰기는 동기입니다
batch/upsert 는 202와 processId를 반환한 뒤 나중에 적용됩니다. 존재하지 않는 ID는 비동기로 실패하지만 호출자에게는 여전히 202가 돌아옵니다. PATCH /v3/companies/{id} 는 204를 반환하며 동기적으로 적용됩니다. 동기화가 성공을 보고한다면, 후속 조회 없이 그 말을 믿을 수 있는 것은 동기 경로뿐입니다.
짧은 연동 체크리스트
- 서비스별, 환경별로 API 키를 분리하고 인사 변동 시 교체합니다.
- 모든 쓰기는 요청 제한 헤더를 읽고 429에서 백오프하는 단일 클라이언트를 거칩니다.
- 시작 시점에 속성 스키마를 검증하고, 속성이 없으면 동기화 실행을 거부합니다.
- 회사 생성에서 409가 나오면 재시도가 아니라 채택입니다.
- 대량 경로는 처리량을 위해 객체 API를 쓰고, 확인이 필요한 작업은 CRM 경로를 씁니다.
- 웹훅은 멱등하고, 배치 처리되며, IP가 제한되고, 공유 시크릿 헤더를 함께 보냅니다.
- 증분 연락처 동기화는 전체 목록 순회가 아니라
modifiedSince를 사용합니다.
이 계층을 만들고 유지하는 일은 실제 엔지니어링 업무입니다. 스키마 검증, 백오프, 채택 로직, 정합성 대조가 모두 필요합니다. Tajo는 바로 그 부담을 흡수하기 위해 존재하며, 재시도와 중복 제거 로직을 손으로 작성하지 않고도 Shopify 및 커머스 데이터를 Brevo 연락처, 회사, 이벤트와 계속 동기화된 상태로 유지합니다. 직접 구축하실 계획이라면, Brevo 연동 가이드가 코드 작성에 앞서 결정해야 할 데이터 모델 선택을 짚어 줍니다.
핵심 정리
- API는
https://api.brevo.com/v3/에 있는 하나의 REST 인터페이스이며, bearer 토큰이 아니라api-key헤더로 인증합니다. - 요청 제한은 극단적으로 불균등합니다. 발송은 사실상 무제한이지만 대부분의 다른 엔드포인트는 표준 요금제에서 시간당 100회를 함께 나눠 씁니다.
- 공식 SDK는 7개 언어로 제공되지만, 엔드포인트 몇 개만 필요하다면 HTTP 인터페이스를 직접 호출해도 될 만큼 단순합니다.
- 샌드박스 모드는 요청 형식만 검증하므로, 발송 외의 것을 테스트하려면 별도 계정을 유지하십시오.
- 2xx 응답은 쓰기가 적용되었다는 증거가 아닙니다. 선언되지 않은 속성은 조용히 버려지고, 객체 업서트는 비동기입니다.
- 고정된 한계를 전제로 설계하십시오. 도메인당 회사 하나, 객체 타입당 100만 레코드, 표준 객체의 일괄 삭제 부재, 그리고 조용히 아무 일도 하지 않는 속성 필터입니다.