EmailmoversMyDataHub docs
Browse the docs

Reference / REST reference

Reference

Create an API key

POST /v1/api-keys. Create a standard key or an agent key.

Generated from the contractsView as Markdown

POST /v1/api-keys

Create a standard key or an agent key. An agent key has a label, allowed tools, a monthly budget, a per-order cap, an expiry and a webhook, and is created by a signed-in person through OAuth, never by a key. An agent key needs allowed_tools and per_order_max_credits and never takes admin. Unlimited keys on every plan; the secret is shown once.

PropertyValue
EndpointPOST https://mydatahub.emailmovers.com/v1/api-keys
Operation idcreateApiKey
CostFree (0 credits)
AccessA signed-in person only: an OAuth 2.1 token with the scope admin. API keys are refused.
Idempotency-KeyOptional. Makes a retry safe.
TagKeys

Request

Parameters

NameInTypeRequiredDescription
MyDataHub-VersionheaderstringnoThe dated API version, pinned per key when left out. Non-breaking changes ship as new dates; the path major changes only for breaking changes, with a 12 month deprecation window.
Idempotency-KeyheaderstringnoMakes the request safe to retry: the same key returns the stored response. Keys are kept for the life of the organisation.

Body

MemberTypeRequiredDescription
kindenum: standard, agentyes
labelstringyes
modeenum: live, testnolive keys (mdh_live_) spend real credits; test keys (mdh_test_) return synthetic data and never charge. Default live.
scopesarray of enum: account:read, counts:read, previews:read, audiences:read, audiences:write, quotes:read, orders:read, orders:write, and 8 moreyesThe key's scopes. An agent key never takes admin, and no key takes account:write, which only a signed-in owner uses.
ip_allowlistarray of stringnoCIDR ranges the key may be used from; empty allows any address.
expires_atstring (date-time)noRFC 3339 date and time, with Z or an offset such as +01:00.
allowed_toolsarray of enum: get_plans, get_account, list_filters, search_filter_values, expand_job_titles, resolve_location, compile_audience, count_audience, and 14 morenoAgent keys only, and required there: the tools the key may call.
allowed_connection_idsarray of stringnoAgent keys only: the connections push_to_crm may push to live. Default none.
monthly_budget_creditsinteger (0 or more)noAgent keys only. Default 1000 credits a month (to confirm).
per_order_max_creditsinteger (0 or more)noAgent keys only, and required there: the most one order may spend, no more than monthly_budget_credits.
webhook_urlstring (uri)noAgent keys only: the https endpoint its events go to.
disclosureenum: account, anonymousnoAgent keys only. anonymous makes every count follow an anonymous visitor's rules, for a public assistant. Default account.
licence_accepted_versionstringnoAgent keys only, and required for one that spends on its own (create_order or enrich_contact, with a monthly budget and a per-order cap above 0): the version of the Data Licence and Sharing Agreement the person making the key accepts, the account's agreements.dlsa.version. Every order and enrichment the key makes on its own carries that acceptance. A key with a budget or cap of 0 needs none: a person approves, and accepts, each of its spends.

Example request

curl -X POST "https://mydatahub.emailmovers.com/v1/api-keys" \
  -H "Authorization: Bearer $MYDATAHUB_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
  "kind": "agent",
  "label": "SDR agent",
  "scopes": [
    "counts:read",
    "quotes:read",
    "orders:write",
    "orders:read",
    "records:read",
    "pushes:write"
  ],
  "allowed_tools": [
    "count_audience",
    "quote_order",
    "create_order",
    "fetch_order_records",
    "push_to_crm"
  ],
  "allowed_connection_ids": ["conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"],
  "monthly_budget_credits": 1000,
  "per_order_max_credits": 500,
  "expires_at": "2027-03-31T00:00:00Z",
  "licence_accepted_version": "1.0"
}'

Responses

201: The key and its secret.

Headers: RateLimit, RateLimit-Policy, Location.

MemberTypeAlways presentDescription
keyStandardApiKey or AgentKeyyesA standard API key or an agent key. The secret is never shown again.
secretstringyesThe secret, shown once. Send it as Authorization: Bearer.

Example response

{
  "key": {
    "id": "key_01JB3Z9R6T1Y5W8ZAK8Q2V7XN3",
    "kind": "agent",
    "label": "SDR agent",
    "mode": "test",
    "prefix": "mdh_test_Exam",
    "scopes": [
      "counts:read",
      "quotes:read",
      "orders:write",
      "orders:read",
      "records:read",
      "pushes:write"
    ],
    "ip_allowlist": [],
    "created_at": "2026-09-20T09:00:00Z",
    "created_by": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8",
    "last_used_at": "2026-09-26T02:00:00Z",
    "expires_at": "2027-03-31T00:00:00Z",
    "revoked_at": null,
    "allowed_tools": [
      "count_audience",
      "quote_order",
      "create_order",
      "fetch_order_records",
      "push_to_crm"
    ],
    "allowed_connection_ids": ["conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"],
    "monthly_budget_credits": 1000,
    "per_order_max_credits": 500,
    "budget": {
      "monthly_credits": 1000,
      "spent": 400,
      "remaining": 600,
      "resets_at": "2026-10-01T00:00:00Z"
    },
    "webhook_url": "https://agent.example.com/mydatahub/events",
    "disclosure": "account"
  },
  "secret": "mdh_test_Example0000000000000000000000000"
}

Errors

Every error is a problem object with a code and a next_step. Every response carries the RateLimit and RateLimit-Policy headers; see Rate limits.

StatusProblem codesWhen
400invalid-request, idempotency-key-required, unsupported-versionThe request could not be read, or an Idempotency-Key is missing.
401authentication-required, account-requiredSign in (OAuth) or send an API key (authentication-required), or create a free account for what the anonymous tier does not cover (account-required).
403insufficient-scope, confirmation-required, business-details-required, licence-acceptance-required, dpa-acceptance-required, agent-budget-exceededThe token lacks a scope (insufficient-scope, with required_scope and a WWW-Authenticate step-up challenge); no person confirmed the spend and no agent key covers it (confirmation-required, with an approval_url); an agent key's per-order cap or monthly budget does not cover it (agent-budget-exceeded); an account made by self-serve sign-up has not yet confirmed its business name and that it is a UK business, which its first order needs (business-details-required); the order needs the Data Licence and Sharing Agreement accepted at the version in force (licence-acceptance-required); or a suppression upload comes before the organisation has accepted the Article 28 data processing agreement in force (dpa-acceptance-required). Nothing is charged.
409idempotency-key-reused, quote-expired, order-not-ready, order-not-cancellableAn Idempotency-Key reused with different parameters, an expired machine quote, or an object in the wrong state.
422validation-failed, quote-required, dataset-unavailableThe request is not valid. errors lists every problem with a JSON pointer and did_you_mean.
429rate-limitedToo many requests. Wait for Retry-After.
Any other failureinternal-error, service-unavailable, tps-screen-expiredSomething failed on our side (500 internal-error) or the service is briefly unavailable (503 service-unavailable, with Retry-After). Nothing was charged; retry with the same Idempotency-Key. A count, sample, quote or order with telephone in play is also refused with 503 tps-screen-expired, with no Retry-After, while the dataset version's TPS and CTPS screen is more than 28 days old.