Share endpoints
Hand a record to another organization, and take delivery of one handed to you.
Authentication, the response envelope, and pagination are on
API conventions. All paths are relative to
https://api-next.expressconsent.com.
POST /v1/cdrs/:cdrId/share | Create a share URL for a record you hold |
POST /v1/shares/:token | Receive a record that was shared with you |
GET /v1/shares/:token | Redirect a person to the dashboard to receive it by hand |
The direction evidence moves and who pays for it is explained on access and collection. This page is the wire format.
POST /v1/cdrs/:cdrId/share
Creates a share URL for a record your organization holds. The body is optional.
curl -sS -X POST -H "X-API-Key: $EC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"expiresInMs": 604800000}' \
"https://api-next.expressconsent.com/v1/cdrs/cdr_abc123/share"{
"ok": true,
"data": {
"token": "xYz7Qw...",
"shareUrl": "https://api-next.expressconsent.com/v1/shares/xYz7Qw...",
"expiresAt": 1741839367890
},
"requestId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301"
}You do not need to have collected a record to share it. Sharing a record you have not paid for is normal for a lead generator whose buyers are the payers.
Request
expiresInMsnumberoptionaldefault2592000000How long the share URL stays usable, in milliseconds from now. The default is 30 days. Read
expiresAton the response for the expiry you actually got.Clamped to a maximum of 2 years. A zero, negative, or non-finite value falls back to the default rather than being rejected, as does any non-number.
Response
tokenstringrequiredThe share token. This is the credential: anyone holding it and an API key for a different organization can take the record.
shareUrlstringrequiredThe absolute URL to hand to the buyer. Identical in form to the
shareUrla capture withautoSharereturns, so the two paths are interchangeable.expiresAtnumberrequiredWhen the token stops working, as a Unix timestamp in milliseconds.
Generating the share URL during the capture instead avoids the extra call altogether. See autoShare
on captureCDR().
POST /v1/shares/:token
Receives a shared record into your organization. The body is optional; sent without one, this saves the record and bills you for it, unless you already have access, or unless the sender had already paid, in which case their access passes to you at no charge.
curl -sS -X POST -H "X-API-Key: $EC_API_KEY" \
"https://api-next.expressconsent.com/v1/shares/xYz7Qw..."{
"ok": true,
"data": {
"claimed": true,
"alreadyClaimed": false,
"cdrId": "cdr_abc123",
"domainId": "example.com",
"shareEventId": "se_9f2b..."
},
"requestId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301"
}Request
collect and acceptance are the only fields this body accepts. Anything else is a 400 INVALID_ARGUMENT naming the offending key. A misspelled acceptance must not quietly mean "no
requirements".
collectbooleanoptionaldefaulttrueWhether to become the payer for this record. With
falsethe record still lands in your account with its metadata and consent facts, and you are not billed.Whether you can download the evidence then depends on the sender. If they had already paid, their access passes to you either way. It is theirs to give, so opting out of payment does not decline it. If they had not, you have no download access until you collect the record later. So
collect: falsemeans "do not make me the payer", not "do not give me access".Any non-boolean value is a 400 INVALID_ARGUMENT rather than being coerced.acceptanceobjectoptionalRequirements the record must meet before you will take it. A record that fails is refused outright: not saved, not charged, and the token stays usable. Fully documented on acceptance criteria.
Response
claimedbooleanrequiredAlways
true. The call either succeeds or returns an error.alreadyClaimedbooleanrequiredtruewhen your organization had already received this record through this token. Repeating the request is safe and never charges twice.cdrIdstringrequiredThe record identifier, now readable through the CDR endpoints.
domainIdstringrequiredThe domain the record is filed under, which you need to list it.
shareEventIdstringrequiredIdentifies this handoff. An empty string when
alreadyClaimedistrue: it is not looked up again on a repeat request.
Once your organization has received a record through a token, the endpoint returns early. acceptance
is not evaluated, and collect: true after a first request that used collect: false neither bills you
nor grants access. To gain access later, collect the record directly.
One token, several recipients
A token is not consumed by being used. It is idempotent per organization, so the same token can hand the same record to several different organizations until it expires. Treat a share token as a bearer credential and give it only to the buyer it is meant for.
Expiry is checked before that idempotency check, so repeating a request for a record you already hold
returns 410 GONE once the token expires rather than reporting it was already received.
You cannot receive your own share
A token created by your organization is refused for your organization with 400 INVALID_ARGUMENT. To
get download access to a record you captured, collect it. See
the CDR endpoints. This is the wall an organization that both generates
and buys leads hits first; generators and buyers explains why.
GET /v1/shares/:token
Redirects to the dashboard, where a person can sign in and take the record by hand. Responds 302 with
a Location of https://app.expressconsent.com/claim/{token}.
This is the only endpoint that needs no API key, because the person following it authenticates in the dashboard instead. It exists so that a share URL pasted into an email is a working link for a human rather than an error.
Nothing is charged by following the redirect. The request that receives the record is the one the dashboard makes afterwards.
Errors
Every code, its HTTP status, and what to do about it is on API errors. The ones specific to these endpoints:
| Status | Code | Cause |
|---|---|---|
| 202 | CDR_PENDING | The record has not finished rendering. Retry after the Retry-After header says to, which is 2 seconds. Note the 2xx status on a failure. |
| 400 | INVALID_ARGUMENT | Your own organization created the token, the body carried an unrecognized field, collect was not a boolean, acceptance did not validate, or acceptance.leadMatch.phone was not a normalizable North American number |
| 403 | PASSTHROUGH_ORG_CANNOT_CLAIM | Your organization has no billing set up and cannot receive shared records on any surface. Such an organization normally has no API access either, in which case API_ACCESS_DISABLED comes back first. |
| 404 | NOT_FOUND | No such token, or no such record on the share path |
| 409 | CONFLICT | On the share path, more than one record on our side carries that identifier. A data problem, not something you caused. |
| 410 | GONE | The token has expired |
| 410 | CDR_INVALID | The record was flagged invalid and cannot be shared or received |
| 422 | CDR_ACCEPTANCE_FAILED | The record did not meet your acceptance requirements |
CDR_PENDING is common immediately after a capture that used autoShare: the token is created during
the upload, so a buyer acting on it within a second or two arrives before the visual record exists. Retry
rather than treating it as a failure.