Dealmoor API

REST API for the Dealmoor CRM: companies, contacts, deals, activities and email drafts. Version 2.3.0. This account holds invented sample data for the Vortner demo.

Reads and writes

Every GET call only reads and changes nothing. Four calls write: creating an email draft, deleting one, sending one, and resetting the sandbox. Sending is the only call that would email someone outside the company; this account has no verified sending domain, so no email is ever delivered. Companies, contacts, deals and activities are read-only through the API.

CallEffect
GET /v1/usersOnly reads
GET /v1/companiesOnly reads
GET /v1/companies/{id}Only reads
GET /v1/contactsOnly reads
GET /v1/contacts/{id}Only reads
GET /v1/dealsOnly reads
GET /v1/deals/{id}Only reads
GET /v1/activitiesOnly reads
GET /v1/email-draftsOnly reads
POST /v1/email-draftsWrites
GET /v1/email-drafts/{id}Only reads
DELETE /v1/email-drafts/{id}Writes
POST /v1/email-drafts/{id}/sendWrites and sends an email
POST /v1/resetWrites

Authentication

Base URL https://crm-demo.vortner.dev. Every /v1 request carries an API key:

curl https://crm-demo.vortner.dev/v1/deals \
  -H "Authorization: Bearer $DEALMOOR_API_KEY"

Each account has two keys. The production key works on the live records. The sandbox key reads the same records, but the drafts it creates, deletes or sends are kept apart from production and are not visible to the production key; a sandbox send is recorded and no email is delivered. Every authenticated response carries X-Dealmoor-Environment: production or sandbox. A missing or wrong key gets 401 unauthorized. An API key sees the whole account, so decide in your integration who may use it.

Rate limits

120 requests per minute per API key, counted in fixed one-minute windows. Every /v1 response carries:

X-RateLimit-Limit120
X-RateLimit-RemainingRequests left in the current window
X-RateLimit-ResetUnix time (seconds) when the window ends

Over the limit the API answers 429 rate_limited with Retry-After in seconds. /openapi.json and this page are not rate limited.

Pagination

The list calls for companies, contacts, deals, activities and email drafts are paginated with page (from 1) and per_page (1 to 100, default 25; larger values get 400). Responses look like:

{
  "data": [ ... ],
  "meta": { "page": 1, "per_page": 25, "total": 31, "total_pages": 2 },
  "links": { "next": "/v1/deals?page=2&per_page=25", "prev": null }
}

Single resources come as {"data": {...}}. The user list is short and returned complete in data.

Errors

{ "error": { "code": "not_found", "message": "No deal with id deal_9999." } }
StatusCodes
400invalid_parameter, invalid_body
401unauthorized
403sending_disabled, sandbox_only
404not_found
405method_not_allowed
409already_sent
422unknown_author, deal_mismatch
429rate_limited

Data model

A company is a customer or prospect with an account owner. A contact works at one company. A deal is with one company and one main contact, has an owner, and moves through the stages lead, qualified, proposal and negotiation until it is won or lost. An activity (call, meeting or note) is logged on a deal by a user. An email draft is written to a contact by a user, optionally about a deal, and stays a draft until it is sent or deleted. Every owner and author is a user of the account, named by email address.

User

FieldTypeDescription
idstringUser id.
namestringFull name.
emailstring (email)Work email address; records name their owner by it.
titlestringJob title.
roleadmin | manager | memberadmin manages the account; manager leads a sales team; member works their own records.

Company

FieldTypeDescription
idstringCompany id.
namestring
domainstringWeb domain; contact addresses use it.
industrystring
citystring
countrystringISO 3166-1 alpha-2 country code.
employee_countintegerApproximate number of employees.
lifecycleprospect | customer | former_customer
owner_emailstring (email)Email address of the account owner, a Dealmoor user.
owner_namestringName of the account owner.
created_atstring (date-time)When the company was added (UTC).

Contact

FieldTypeDescription
idstringContact id.
company_idstringThe company the contact works at.
first_namestring
last_namestring
emailstring (email)Work email address; email drafts go here.
job_titlestring
owner_emailstring (email)Email address of the user who owns the contact.
owner_namestringName of the user who owns the contact.
created_atstring (date-time)When the contact was added (UTC).

Deal

FieldTypeDescription
idstringDeal id.
namestringWhat is being sold.
company_idstringThe customer or prospect company.
company_namestringName of that company.
contact_idstringThe main contact at the company.
owner_emailstring (email)Email address of the deal owner, the user responsible for the deal.
owner_namestringName of the deal owner.
typenew_business | expansion | renewal
stagelead | qualified | proposal | negotiation | closed_won | closed_lost
statusopen | won | lost
probabilityintegerChance of winning in percent, set by the stage (lead 10, qualified 25, proposal 50, negotiation 75, won 100, lost 0).
amountnumberDeal value, net, in currency.
currencyEURISO 4217 currency code.
expected_close_datestring (date)When the deal is expected to close; for a closed deal, the day it closed.
closed_onstring | null (date)The day the deal was won or lost; null while open.
lost_reasonstring | nullWhy a lost deal was lost; null otherwise.
created_atstring (date-time)When the deal was created (UTC).

Activity

FieldTypeDescription
idstringActivity id.
deal_idstringThe deal the activity was logged on.
contact_idstring | nullThe contact involved, if any.
typecall | meeting | note
subjectstringOne-line summary.
notesstringWhat happened, in the words of the user who logged it.
owner_emailstring (email)Email address of the user who logged the activity.
owner_namestringName of the user who logged the activity.
occurred_atstring (date-time)When the call or meeting took place, or the note was written (UTC).
duration_minutesinteger | nullLength of a call or meeting in minutes; null for a note.

EmailDraft

FieldTypeDescription
idstringEmail draft id.
contact_idstringThe contact the email is to.
deal_idstring | nullThe deal the email is about, if any.
author_emailstring (email)Email address of the user who wrote it; the email is sent from this address.
author_namestringName of the user who wrote it.
tostring (email)Recipient: the contact's email address.
subjectstringSubject line.
bodystringPlain-text body.
statusdraft | sent
created_atstring (date-time)When the draft was created (UTC).
sent_atstring | null (date-time)When it was sent (UTC); null while a draft.

Endpoints

GET /openapi.json Only reads

Get this API description

Returns this OpenAPI 3.1 document. No API key is needed and the request does not count toward the rate limit. Only reads; changes nothing.

GET /v1/users Only reads

List users

Returns every user with a seat in the account: name, email address, job title and Dealmoor role. The list is complete and not paginated. Only reads; changes nothing.

GET /v1/companies Only reads

List companies

Returns the companies of the account, ordered by id. Filters combine with AND. Only reads; changes nothing.

ParameterInRequiredTypeDescription
pagequerynointegerPage number, starting at 1.
per_pagequerynointegerItems per page, at most 100.
owner_emailquerynostring (email)Only companies owned by the user with this email address (exact match, case-insensitive).
lifecyclequerynoprospect | customer | former_customerOnly companies at this point in the relationship.
qquerynostringOnly companies whose name or domain contains this text (case-insensitive).

GET /v1/companies/{id} Only reads

Get a company

Returns one company by id. Only reads; changes nothing.

ParameterInRequiredTypeDescription
idpathyesstringCompany id.

GET /v1/contacts Only reads

List contacts

Returns the contacts of the account, ordered by id. Filters combine with AND. Only reads; changes nothing.

ParameterInRequiredTypeDescription
pagequerynointegerPage number, starting at 1.
per_pagequerynointegerItems per page, at most 100.
company_idquerynostringOnly contacts at this company.
owner_emailquerynostring (email)Only contacts owned by the user with this email address (exact match, case-insensitive).
emailquerynostring (email)Only the contact with this email address (exact match, case-insensitive).

GET /v1/contacts/{id} Only reads

Get a contact

Returns one contact by id. Only reads; changes nothing.

ParameterInRequiredTypeDescription
idpathyesstringContact id.

GET /v1/deals Only reads

List deals

Returns the deals of the account, ordered by id: open deals in the pipeline and deals already won or lost. Filters combine with AND; filter by status open for the current pipeline. Only reads; changes nothing.

ParameterInRequiredTypeDescription
pagequerynointegerPage number, starting at 1.
per_pagequerynointegerItems per page, at most 100.
owner_emailquerynostring (email)Only deals owned by the user with this email address (exact match, case-insensitive).
stagequerynolead | qualified | proposal | negotiation | closed_won | closed_lostOnly deals at this pipeline stage.
statusquerynoopen | won | lostOnly open, won or lost deals.
typequerynonew_business | expansion | renewalOnly deals of this type.
company_idquerynostringOnly deals with this company.

GET /v1/deals/{id} Only reads

Get a deal

Returns one deal by id. Only reads; changes nothing.

ParameterInRequiredTypeDescription
idpathyesstringDeal id.

GET /v1/activities Only reads

List activities

Returns the calls, meetings and notes logged on deals, ordered by id. The owner is the user who logged the activity, who is not always the deal's owner. Filters combine with AND. Only reads; changes nothing.

ParameterInRequiredTypeDescription
pagequerynointegerPage number, starting at 1.
per_pagequerynointegerItems per page, at most 100.
deal_idquerynostringOnly activities on this deal.
owner_emailquerynostring (email)Only activities owned by the user with this email address (exact match, case-insensitive).
typequerynocall | meeting | noteOnly activities of this type.

GET /v1/email-drafts Only reads

List email drafts

Returns the email drafts of the account, ordered by id, including drafts already sent. Filters combine with AND. Only reads; changes nothing.

ParameterInRequiredTypeDescription
pagequerynointegerPage number, starting at 1.
per_pagequerynointegerItems per page, at most 100.
contact_idquerynostringOnly drafts to this contact.
author_emailquerynostring (email)Only drafts written by the user with this email address (exact match, case-insensitive).
statusquerynodraft | sentOnly drafts with this status.

POST /v1/email-drafts Writes

Create an email draft

Writes: creates an email draft to a contact, written by a Dealmoor user. Nothing is sent: the draft waits with status draft until someone sends or deletes it. The recipient is the contact's email address. A deal_id, when given, must be a deal with the contact's company.

Body (JSON):

FieldRequiredTypeDescription
contact_idyesstringThe contact to write to.
deal_idnostring | nullOptional: a deal with the contact's company that the email is about.
author_emailyesstring (email)Email address of the Dealmoor user writing the draft.
subjectyesstringSubject line.
bodyyesstringPlain-text body.

GET /v1/email-drafts/{id} Only reads

Get an email draft

Returns one email draft by id, with its subject, body, recipient and status. Only reads; changes nothing.

ParameterInRequiredTypeDescription
idpathyesstringEmail draft id.

DELETE /v1/email-drafts/{id} Writes

Delete an email draft

Writes: deletes an email draft that has not been sent. A sent email stays on record and cannot be deleted (409 already_sent).

ParameterInRequiredTypeDescription
idpathyesstringEmail draft id.

POST /v1/email-drafts/{id}/send Writes and sends an email

Send an email draft

Writes and sends: sends the draft as an email from its author to the contact, and marks it sent. A sent email cannot be recalled. This account has no verified sending domain, so with the production key the call answers 403 sending_disabled and nothing changes. With the sandbox key the send is recorded (status sent, sent_at set) and no email is delivered. No request body.

ParameterInRequiredTypeDescription
idpathyesstringEmail draft id.

POST /v1/reset Writes

Reset the sandbox

Writes: clears everything the sandbox key has written (drafts created, drafts deleted, sends recorded), so the sandbox shows the account as it was. Sandbox key only; the production key gets 403 sandbox_only. No request body.