Conversions
Conversions endpoints of the URLCrop API: 5 operations. Server-side Conversions API (Phase 2, Business plan). Attribution via click_id, coupon or customer.
List conversions
GET/conversions
- Scope conversions:read
- business plan and above
- Coming soon
Coming soon: this endpoint is documented ahead of its release and is not available yet.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| X-Workspace-Id | header | string | Workspace to act on. Required for session requests on workspace-scoped routes; optional for API keys (must equal the key's workspace, otherwise 403 workspace_mismatch). For a session, a workspace the user is not an active member of (another tenant, a removed membership, a malformed or unknown id) answers 404 resource_not_found, never 403. |
| cursor | query | string | Opaque cursor from pagination.next_cursor. |
| limit | query | integer | Page size (1–100). |
| event | query | string | One of: lead, signup, add_to_cart, purchase, custom |
| status | query | string | One of: queued, attributed, unattributed, duplicate, rejected |
| link_id | query | string | |
| campaign_id | query | string | |
| source | query | string | |
| occurred_after | query | string | |
| occurred_before | query | string |
Request example
curl 'https://api.urlcrop.com/v1/conversions' \
-H 'Authorization: Bearer uc_live_…'Responses
200 response
Conversions
ConversionList schema and example
Field Type Description datarequired array of Conversion data[]. idrequired string data[]. objectrequired string Value: conversiondata[]. workspace_idrequired string data[]. is_testrequired boolean data[]. eventrequired string One of: lead,signup,add_to_cart,purchase,customdata[]. event_name string | null Free-form name when eventiscustom.data[]. statusrequired string queued→attributed|unattributed;duplicateandrejectedare terminal.One of:queued,attributed,unattributed,duplicate,rejecteddata[]. click_id string | null data[]. link_id string | null data[]. qr_code_id string | null data[]. campaign_id string | null data[]. partner_id string | null Phase 3. data[]. order_id string | null data[]. external_id string | null data[]. value Money | null data[]. value. amountrequired integer Integer minor units (paise, cents). Never a float. data[]. value. currencyrequired string ISO 4217 code.One of: INR,USDdata[]. customer ConversionCustomer | null data[]. customer. external_id string max length 128 data[]. customer. email_hash string data[]. customer. phone_hash string SHA-256 of the E.164 number. data[]. coupon_code string | null data[]. sourcerequired string One of: api,snippet,shopify,woocommerce,razorpay,paypal,testdata[]. attribution_method string | null One of: click_id,coupon_code,customer,nulldata[]. occurred_atrequired string ISO 8601 UTC with milliseconds.Format: date-time data[]. attributed_at string | null Format: date-time data[]. metadata Metadata Up to 20 keys (≤ 40 chars) with string values (≤ 500 chars). Stored verbatim.max keys 20 data[]. created_atrequired string ISO 8601 UTC with milliseconds.Format: date-time paginationrequired Pagination pagination. limitrequired integer pagination. has_morerequired boolean pagination. next_cursorrequired string | null Pass as cursorto fetch the next page.nullon the last page.pagination. total integer Only with include_total=true; estimated above 10,000.200 response: 200 responseJSON{ "data": [ { "id": "cnv_01JB59ZZY8X7W6V5U4T3S2R1Q0", "object": "conversion", "workspace_id": "ws_01JB4M0A1B2C3D4E5F6G7H8J9K", "is_test": false, "event": "lead", "event_name": "string", "status": "queued", "click_id": "string", "link_id": "string", "qr_code_id": "string", "campaign_id": "string", "partner_id": "string", "order_id": "string", "external_id": "string", "value": { "amount": 149900, "currency": "INR" }, "customer": { "external_id": "string", "email_hash": "string", "phone_hash": "string" }, "coupon_code": "string", "source": "api", "attribution_method": "click_id", "occurred_at": "2026-12-05T10:15:30.000Z", "attributed_at": "2026-12-05T10:15:30.000Z", "metadata": {}, "created_at": "2026-12-05T10:15:30.000Z" } ], "pagination": { "limit": 0, "has_more": false, "next_cursor": "string", "total": 0 } }Example generated from the schema. 401 response
Missing or invalid credentials. Always
code: unauthenticated;details[0].codegives the reason (missing_credentials,invalid_api_key,api_key_revoked,api_key_expired,session_expired,publishable_key_not_allowed).Error codes:
unauthenticatedError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 401 response: unauthenticatedJSON{ "error": { "type": "authentication_error", "code": "unauthenticated", "message": "The API key is not valid.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#unauthenticated", "details": [ { "path": "Authorization", "code": "invalid_api_key", "message": "No key matches this secret" } ] } }403 response
Permitted credential but not allowed:
insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,two_factor_required(also Owner/Admin writes on Business+ after the 14-day 2FA grace,details[0].grace_ends_at),step_up_required,email_verification_required,signups_paused(sign-up while the platform setting is on),write_blocked_past_due,workspace_suspended,content_policy_hold,origin_not_allowed, or a plan limit (type: plan_limit_error—feature_not_in_plan,plan_limit_reachedwithparamnaming the plan limit key). Any credentialed operation can return it: an API key on a session-only route isinsufficient_scope, a session write without an allowedOriginisorigin_not_allowed, and an API key whose plan has no API access isfeature_not_in_plan.Error codes:
two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,feature_not_in_plan,plan_limit_reachedError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 403 response: plan limit reachedJSON{ "error": { "type": "plan_limit_error", "code": "plan_limit_reached", "message": "You have created 2,000 of 2,000 links this billing period. Upgrade or buy a pack to continue.", "param": "links_per_month", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/pricing", "details": [ { "code": "plan_limit_reached", "message": "Monthly link quota reached", "limit": 2000, "used": 2000, "resets_at": "2026-12-01T00:00:00.000Z", "upgrade_to": "business" } ] } }403 response: feature not in planJSON{ "error": { "type": "plan_limit_error", "code": "feature_not_in_plan", "message": "The public API is available on the Pro plan and above.", "param": "api_requests_per_day", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/pricing", "details": [ { "code": "feature_not_in_plan", "message": "Upgrade to Pro", "upgrade_to": "pro" } ] } }403 response: email verification requiredJSON{ "error": { "type": "permission_error", "code": "email_verification_required", "message": "Verify your email address to create links.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#email_verification_required" } }403 response: step up requiredJSON{ "error": { "type": "permission_error", "code": "step_up_required", "message": "Confirm your password or 2FA code to continue.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#step_up_required" } }404 response
Unknown id, or the resource belongs to another workspace (never distinguished). Also returned when a session's
X-Workspace-Idnames a workspace the user is not an active member of.Error codes:
resource_not_foundError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 404 response: not foundJSON{ "error": { "type": "not_found_error", "code": "resource_not_found", "message": "No link with id lnk_01JB4N8ZK3Q9WXYZ0123456789.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#resource_not_found" } }
Record a conversion (server-side Conversions API)
POST/conversions
- Scope conversions:write
- business plan and above
- Coming soon
Coming soon: this endpoint is documented ahead of its release and is not available yet.
Phase 2, Business plan and above. Attribution runs asynchronously: click_id first, then coupon_code, then hashed customer identifiers (90-day window). (event, order_id) is deduplicated for 7 days — a repeat returns 200 with status: duplicate. When the monthly event quota is exhausted the call fails with 403 plan_limit_reached (param: events_per_month).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| X-Workspace-Id | header | string | Workspace to act on. Required for session requests on workspace-scoped routes; optional for API keys (must equal the key's workspace, otherwise 403 workspace_mismatch). For a session, a workspace the user is not an active member of (another tenant, a removed membership, a malformed or unknown id) answers 404 resource_not_found, never 403. |
| Idempotency-Key | header | string | Unique string (UUID v4 recommended, ≤ 255 chars). Repeating a POST with the same key and body within 24 hours replays the original response with Idempotent-Replayed: true. One-time secrets are never cached: a replay returns them as null with Idempotent-Redacted: secret. |
Request body application/json
| Field | Type | Description |
|---|---|---|
| eventrequired | string | One of: lead, signup, add_to_cart, purchase, custom |
| event_name | string | max length 64 |
| click_id | string | From the ucid query parameter / _ucid cookie. |
| order_id | string | Deduplication key with event for 7 days.max length 128 |
| external_id | string | max length 128 |
| value | Money | |
| value. | integer | Integer minor units (paise, cents). Never a float. |
| value. | string | ISO 4217 code.One of: INR, USD |
| customer | ConversionCustomer | Hashed identifiers only. Lower-case and trim before hashing with SHA-256 (hex). |
| customer. | string | max length 128 |
| customer. | string | |
| customer. | string | SHA-256 of the E.164 number. |
| coupon_code | string | max length 64 |
| occurred_at | string | ISO 8601 UTC with milliseconds.Format: date-time |
| metadata | Metadata | Up to 20 keys (≤ 40 chars) with string values (≤ 500 chars). Stored verbatim.max keys 20 |
{
"event": "purchase",
"click_id": "clk_01JB59XQ0P1N2M3L4K5J6H7G8F",
"order_id": "SHOP-10045",
"value": {
"amount": 249900,
"currency": "INR"
},
"coupon_code": "PRIYA10",
"customer": {
"external_id": "cust_41",
"email_hash": "5d41402abc4b2a76b9719d911017c592ab1c7a6f2c3d4e5f60718293a4b5c6d7"
},
"occurred_at": "2027-02-14T09:01:58.000Z"
}{
"event": "lead",
"coupon_code": "PRIYA10",
"external_id": "lead_8812"
}Request example
curl -X POST 'https://api.urlcrop.com/v1/conversions' \
-H 'Authorization: Bearer uc_live_…' \
-H 'Content-Type: application/json' \
-d '{
"event": "purchase",
"click_id": "clk_01JB59XQ0P1N2M3L4K5J6H7G8F",
"order_id": "SHOP-10045",
"value": {
"amount": 249900,
"currency": "INR"
},
"coupon_code": "PRIYA10",
"customer": {
"external_id": "cust_41",
"email_hash": "5d41402abc4b2a76b9719d911017c592ab1c7a6f2c3d4e5f60718293a4b5c6d7"
},
"occurred_at": "2027-02-14T09:01:58.000Z"
}'Responses
200 response
Duplicate of an earlier conversion
ConversionAccepted schema and example
Field Type Description idrequired string objectrequired string Value: conversionstatusrequired string One of: queued,duplicateduplicate_of string | null 200 response: 200 responseJSON{ "id": "string", "object": "conversion", "status": "queued", "duplicate_of": "string" }Example generated from the schema. 202 response
Accepted for attribution
ConversionAccepted schema and example
Field Type Description idrequired string objectrequired string Value: conversionstatusrequired string One of: queued,duplicateduplicate_of string | null 202 response: queuedJSON{ "id": "cnv_01JB59ZZY8X7W6V5U4T3S2R1Q0", "object": "conversion", "status": "queued", "duplicate_of": null }401 response
Missing or invalid credentials. Always
code: unauthenticated;details[0].codegives the reason (missing_credentials,invalid_api_key,api_key_revoked,api_key_expired,session_expired,publishable_key_not_allowed).Error codes:
unauthenticatedError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 401 response: unauthenticatedJSON{ "error": { "type": "authentication_error", "code": "unauthenticated", "message": "The API key is not valid.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#unauthenticated", "details": [ { "path": "Authorization", "code": "invalid_api_key", "message": "No key matches this secret" } ] } }403 response
Permitted credential but not allowed:
insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,two_factor_required(also Owner/Admin writes on Business+ after the 14-day 2FA grace,details[0].grace_ends_at),step_up_required,email_verification_required,signups_paused(sign-up while the platform setting is on),write_blocked_past_due,workspace_suspended,content_policy_hold,origin_not_allowed, or a plan limit (type: plan_limit_error—feature_not_in_plan,plan_limit_reachedwithparamnaming the plan limit key). Any credentialed operation can return it: an API key on a session-only route isinsufficient_scope, a session write without an allowedOriginisorigin_not_allowed, and an API key whose plan has no API access isfeature_not_in_plan.Error codes:
two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,feature_not_in_plan,plan_limit_reachedError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 403 response: plan limit reachedJSON{ "error": { "type": "plan_limit_error", "code": "plan_limit_reached", "message": "You have created 2,000 of 2,000 links this billing period. Upgrade or buy a pack to continue.", "param": "links_per_month", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/pricing", "details": [ { "code": "plan_limit_reached", "message": "Monthly link quota reached", "limit": 2000, "used": 2000, "resets_at": "2026-12-01T00:00:00.000Z", "upgrade_to": "business" } ] } }403 response: feature not in planJSON{ "error": { "type": "plan_limit_error", "code": "feature_not_in_plan", "message": "The public API is available on the Pro plan and above.", "param": "api_requests_per_day", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/pricing", "details": [ { "code": "feature_not_in_plan", "message": "Upgrade to Pro", "upgrade_to": "pro" } ] } }403 response: email verification requiredJSON{ "error": { "type": "permission_error", "code": "email_verification_required", "message": "Verify your email address to create links.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#email_verification_required" } }403 response: step up requiredJSON{ "error": { "type": "permission_error", "code": "step_up_required", "message": "Confirm your password or 2FA code to continue.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#step_up_required" } }404 response
Unknown id, or the resource belongs to another workspace (never distinguished). Also returned when a session's
X-Workspace-Idnames a workspace the user is not an active member of.Error codes:
resource_not_foundError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 404 response: not foundJSON{ "error": { "type": "not_found_error", "code": "resource_not_found", "message": "No link with id lnk_01JB4N8ZK3Q9WXYZ0123456789.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#resource_not_found" } }422 response
Validation failure (
validation_failed,destination_invalid,destination_blocked(details[0].codeispolicy_violation, with the category, for content-policy blocks),slug_invalid,slug_reserved,slug_not_allowed,handle_not_allowed,title_not_allowed,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,policy_acceptance_required, …).Error codes:
validation_failed,destination_invalid,destination_blocked,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,policy_acceptance_requiredError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 422 response: validation failedJSON{ "error": { "type": "validation_error", "code": "validation_failed", "message": "The request body is invalid.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#validation_failed", "details": [ { "path": "destination_url", "code": "invalid_string", "message": "Must be an absolute http(s) URL" } ] } }422 response: destination blockedJSON{ "error": { "type": "validation_error", "code": "destination_blocked", "message": "This destination was flagged as unsafe and cannot be shortened.", "param": "destination_url", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#destination_blocked" } }429 response
Burst limit, daily plan quota or endpoint limit exceeded.
Error codes:
rate_limitedError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 429 response: rate limitedJSON{ "error": { "type": "rate_limit_error", "code": "rate_limited", "message": "Daily API quota of 50,000 requests exhausted. Resets at 00:00 UTC.", "param": "daily_quota", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/rate-limits" } }
Record up to 500 conversions
POST/conversions/batch
- Scope conversions:write
- business plan and above
- Coming soon
Coming soon: this endpoint is documented ahead of its release and is not available yet.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| X-Workspace-Id | header | string | Workspace to act on. Required for session requests on workspace-scoped routes; optional for API keys (must equal the key's workspace, otherwise 403 workspace_mismatch). For a session, a workspace the user is not an active member of (another tenant, a removed membership, a malformed or unknown id) answers 404 resource_not_found, never 403. |
| Idempotency-Key | header | string | Unique string (UUID v4 recommended, ≤ 255 chars). Repeating a POST with the same key and body within 24 hours replays the original response with Idempotent-Replayed: true. One-time secrets are never cached: a replay returns them as null with Idempotent-Redacted: secret. |
Request body application/json
| Field | Type | Description |
|---|---|---|
| conversionsrequired | array of ConversionCreate | min items 1, max items 500 |
| conversions[]. | string | One of: lead, signup, add_to_cart, purchase, custom |
| conversions[]. | string | max length 64 |
| conversions[]. | string | From the ucid query parameter / _ucid cookie. |
| conversions[]. | string | Deduplication key with event for 7 days.max length 128 |
| conversions[]. | string | max length 128 |
| conversions[]. | Money | |
| conversions[]. | integer | Integer minor units (paise, cents). Never a float. |
| conversions[]. | string | ISO 4217 code.One of: INR, USD |
| conversions[]. | ConversionCustomer | Hashed identifiers only. Lower-case and trim before hashing with SHA-256 (hex). |
| conversions[]. | string | max length 128 |
| conversions[]. | string | |
| conversions[]. | string | SHA-256 of the E.164 number. |
| conversions[]. | string | max length 64 |
| conversions[]. | string | ISO 8601 UTC with milliseconds.Format: date-time |
| conversions[]. | Metadata | Up to 20 keys (≤ 40 chars) with string values (≤ 500 chars). Stored verbatim.max keys 20 |
{
"conversions": [
{
"event": "lead",
"event_name": "string",
"click_id": "clk_01JB59XQ0P1N2M3L4K5J6H7G8F",
"order_id": "string",
"external_id": "string",
"value": {
"amount": 149900,
"currency": "INR"
},
"customer": {
"external_id": "string",
"email_hash": "string",
"phone_hash": "string"
},
"coupon_code": "string",
"occurred_at": "2026-12-05T10:15:30.000Z",
"metadata": {}
}
]
}Request example
curl -X POST 'https://api.urlcrop.com/v1/conversions/batch' \
-H 'Authorization: Bearer uc_live_…' \
-H 'Content-Type: application/json' \
-d '{
"conversions": [
{
"event": "lead",
"event_name": "string",
"click_id": "clk_01JB59XQ0P1N2M3L4K5J6H7G8F",
"order_id": "string",
"external_id": "string",
"value": {
"amount": 149900,
"currency": "INR"
},
"customer": {
"external_id": "string",
"email_hash": "string",
"phone_hash": "string"
},
"coupon_code": "string",
"occurred_at": "2026-12-05T10:15:30.000Z",
"metadata": {}
}
]
}'Responses
202 response
Per-row outcome
ConversionBatchResult schema and example
Field Type Description acceptedrequired array of object accepted[]. indexrequired integer accepted[]. idrequired string rejectedrequired array of object rejected[]. indexrequired integer rejected[]. coderequired string rejected[]. messagerequired string rejected[]. param string 202 response: mixedJSON{ "accepted": [ { "index": 0, "id": "cnv_01JB59ZZY8X7W6V5U4T3S2R1Q0" } ], "rejected": [ { "index": 1, "code": "attribution_key_missing", "message": "Provide click_id, coupon_code or customer.", "param": "click_id" } ] }401 response
Missing or invalid credentials. Always
code: unauthenticated;details[0].codegives the reason (missing_credentials,invalid_api_key,api_key_revoked,api_key_expired,session_expired,publishable_key_not_allowed).Error codes:
unauthenticatedError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 401 response: unauthenticatedJSON{ "error": { "type": "authentication_error", "code": "unauthenticated", "message": "The API key is not valid.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#unauthenticated", "details": [ { "path": "Authorization", "code": "invalid_api_key", "message": "No key matches this secret" } ] } }403 response
Permitted credential but not allowed:
insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,two_factor_required(also Owner/Admin writes on Business+ after the 14-day 2FA grace,details[0].grace_ends_at),step_up_required,email_verification_required,signups_paused(sign-up while the platform setting is on),write_blocked_past_due,workspace_suspended,content_policy_hold,origin_not_allowed, or a plan limit (type: plan_limit_error—feature_not_in_plan,plan_limit_reachedwithparamnaming the plan limit key). Any credentialed operation can return it: an API key on a session-only route isinsufficient_scope, a session write without an allowedOriginisorigin_not_allowed, and an API key whose plan has no API access isfeature_not_in_plan.Error codes:
two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,feature_not_in_plan,plan_limit_reachedError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 403 response: plan limit reachedJSON{ "error": { "type": "plan_limit_error", "code": "plan_limit_reached", "message": "You have created 2,000 of 2,000 links this billing period. Upgrade or buy a pack to continue.", "param": "links_per_month", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/pricing", "details": [ { "code": "plan_limit_reached", "message": "Monthly link quota reached", "limit": 2000, "used": 2000, "resets_at": "2026-12-01T00:00:00.000Z", "upgrade_to": "business" } ] } }403 response: feature not in planJSON{ "error": { "type": "plan_limit_error", "code": "feature_not_in_plan", "message": "The public API is available on the Pro plan and above.", "param": "api_requests_per_day", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/pricing", "details": [ { "code": "feature_not_in_plan", "message": "Upgrade to Pro", "upgrade_to": "pro" } ] } }403 response: email verification requiredJSON{ "error": { "type": "permission_error", "code": "email_verification_required", "message": "Verify your email address to create links.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#email_verification_required" } }403 response: step up requiredJSON{ "error": { "type": "permission_error", "code": "step_up_required", "message": "Confirm your password or 2FA code to continue.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#step_up_required" } }404 response
Unknown id, or the resource belongs to another workspace (never distinguished). Also returned when a session's
X-Workspace-Idnames a workspace the user is not an active member of.Error codes:
resource_not_foundError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 404 response: not foundJSON{ "error": { "type": "not_found_error", "code": "resource_not_found", "message": "No link with id lnk_01JB4N8ZK3Q9WXYZ0123456789.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#resource_not_found" } }413 response
Payload too large
Error codes:
invalid_jsonError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 413 response: 413 responseJSON{ "error": { "type": "invalid_request_error", "code": "invalid_json", "message": "string", "param": "string", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://example.com", "details": [ { "path": "string", "code": "string", "message": "string", "limit": 0, "used": 0, "resets_at": "2026-12-05T10:15:30.000Z", "upgrade_to": "string" } ] } }Example generated from the schema. 422 response
Validation failure (
validation_failed,destination_invalid,destination_blocked(details[0].codeispolicy_violation, with the category, for content-policy blocks),slug_invalid,slug_reserved,slug_not_allowed,handle_not_allowed,title_not_allowed,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,policy_acceptance_required, …).Error codes:
validation_failed,destination_invalid,destination_blocked,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,policy_acceptance_requiredError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 422 response: validation failedJSON{ "error": { "type": "validation_error", "code": "validation_failed", "message": "The request body is invalid.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#validation_failed", "details": [ { "path": "destination_url", "code": "invalid_string", "message": "Must be an absolute http(s) URL" } ] } }422 response: destination blockedJSON{ "error": { "type": "validation_error", "code": "destination_blocked", "message": "This destination was flagged as unsafe and cannot be shortened.", "param": "destination_url", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#destination_blocked" } }
Get a conversion
GET/conversions/{id}
- Scope conversions:read
- business plan and above
- Coming soon
Coming soon: this endpoint is documented ahead of its release and is not available yet.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| idrequired | path | string | Prefixed ULID (<prefix>_<26 Crockford base32 chars>). |
| X-Workspace-Id | header | string | Workspace to act on. Required for session requests on workspace-scoped routes; optional for API keys (must equal the key's workspace, otherwise 403 workspace_mismatch). For a session, a workspace the user is not an active member of (another tenant, a removed membership, a malformed or unknown id) answers 404 resource_not_found, never 403. |
Request example
curl 'https://api.urlcrop.com/v1/conversions/lnk_01JB4N8ZK3Q9WXYZ0123456789' \
-H 'Authorization: Bearer uc_live_…'Responses
200 response
Conversion
Conversion schema and example
Field Type Description idrequired string objectrequired string Value: conversionworkspace_idrequired string is_testrequired boolean eventrequired string One of: lead,signup,add_to_cart,purchase,customevent_name string | null Free-form name when eventiscustom.statusrequired string queued→attributed|unattributed;duplicateandrejectedare terminal.One of:queued,attributed,unattributed,duplicate,rejectedclick_id string | null link_id string | null qr_code_id string | null campaign_id string | null partner_id string | null Phase 3. order_id string | null external_id string | null value Money | null value. amountrequired integer Integer minor units (paise, cents). Never a float. value. currencyrequired string ISO 4217 code.One of: INR,USDcustomer ConversionCustomer | null customer. external_id string max length 128 customer. email_hash string customer. phone_hash string SHA-256 of the E.164 number. coupon_code string | null sourcerequired string One of: api,snippet,shopify,woocommerce,razorpay,paypal,testattribution_method string | null One of: click_id,coupon_code,customer,nulloccurred_atrequired string ISO 8601 UTC with milliseconds.Format: date-time attributed_at string | null Format: date-time metadata Metadata Up to 20 keys (≤ 40 chars) with string values (≤ 500 chars). Stored verbatim.max keys 20 created_atrequired string ISO 8601 UTC with milliseconds.Format: date-time 200 response: 200 responseJSON{ "id": "cnv_01JB59ZZY8X7W6V5U4T3S2R1Q0", "object": "conversion", "workspace_id": "ws_01JB4M0A1B2C3D4E5F6G7H8J9K", "is_test": false, "event": "lead", "event_name": "string", "status": "queued", "click_id": "string", "link_id": "string", "qr_code_id": "string", "campaign_id": "string", "partner_id": "string", "order_id": "string", "external_id": "string", "value": { "amount": 149900, "currency": "INR" }, "customer": { "external_id": "string", "email_hash": "string", "phone_hash": "string" }, "coupon_code": "string", "source": "api", "attribution_method": "click_id", "occurred_at": "2026-12-05T10:15:30.000Z", "attributed_at": "2026-12-05T10:15:30.000Z", "metadata": {}, "created_at": "2026-12-05T10:15:30.000Z" }Example generated from the schema. 401 response
Missing or invalid credentials. Always
code: unauthenticated;details[0].codegives the reason (missing_credentials,invalid_api_key,api_key_revoked,api_key_expired,session_expired,publishable_key_not_allowed).Error codes:
unauthenticatedError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 401 response: unauthenticatedJSON{ "error": { "type": "authentication_error", "code": "unauthenticated", "message": "The API key is not valid.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#unauthenticated", "details": [ { "path": "Authorization", "code": "invalid_api_key", "message": "No key matches this secret" } ] } }404 response
Unknown id, or the resource belongs to another workspace (never distinguished). Also returned when a session's
X-Workspace-Idnames a workspace the user is not an active member of.Error codes:
resource_not_foundError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 404 response: not foundJSON{ "error": { "type": "not_found_error", "code": "resource_not_found", "message": "No link with id lnk_01JB4N8ZK3Q9WXYZ0123456789.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#resource_not_found" } }
Reject a conversion (order cancelled, fraud)
DELETE/conversions/{id}
- Scope conversions:write
- business plan and above
- Coming soon
Coming soon: this endpoint is documented ahead of its release and is not available yet.
Marks it rejected; revenue leaves the roll-ups. This is a data correction only — it has no billing effect.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| idrequired | path | string | Prefixed ULID (<prefix>_<26 Crockford base32 chars>). |
| X-Workspace-Id | header | string | Workspace to act on. Required for session requests on workspace-scoped routes; optional for API keys (must equal the key's workspace, otherwise 403 workspace_mismatch). For a session, a workspace the user is not an active member of (another tenant, a removed membership, a malformed or unknown id) answers 404 resource_not_found, never 403. |
Request example
curl -X DELETE 'https://api.urlcrop.com/v1/conversions/lnk_01JB4N8ZK3Q9WXYZ0123456789' \
-H 'Authorization: Bearer uc_live_…'Responses
200 response
Rejected
Conversion schema and example
Field Type Description idrequired string objectrequired string Value: conversionworkspace_idrequired string is_testrequired boolean eventrequired string One of: lead,signup,add_to_cart,purchase,customevent_name string | null Free-form name when eventiscustom.statusrequired string queued→attributed|unattributed;duplicateandrejectedare terminal.One of:queued,attributed,unattributed,duplicate,rejectedclick_id string | null link_id string | null qr_code_id string | null campaign_id string | null partner_id string | null Phase 3. order_id string | null external_id string | null value Money | null value. amountrequired integer Integer minor units (paise, cents). Never a float. value. currencyrequired string ISO 4217 code.One of: INR,USDcustomer ConversionCustomer | null customer. external_id string max length 128 customer. email_hash string customer. phone_hash string SHA-256 of the E.164 number. coupon_code string | null sourcerequired string One of: api,snippet,shopify,woocommerce,razorpay,paypal,testattribution_method string | null One of: click_id,coupon_code,customer,nulloccurred_atrequired string ISO 8601 UTC with milliseconds.Format: date-time attributed_at string | null Format: date-time metadata Metadata Up to 20 keys (≤ 40 chars) with string values (≤ 500 chars). Stored verbatim.max keys 20 created_atrequired string ISO 8601 UTC with milliseconds.Format: date-time 200 response: 200 responseJSON{ "id": "cnv_01JB59ZZY8X7W6V5U4T3S2R1Q0", "object": "conversion", "workspace_id": "ws_01JB4M0A1B2C3D4E5F6G7H8J9K", "is_test": false, "event": "lead", "event_name": "string", "status": "queued", "click_id": "string", "link_id": "string", "qr_code_id": "string", "campaign_id": "string", "partner_id": "string", "order_id": "string", "external_id": "string", "value": { "amount": 149900, "currency": "INR" }, "customer": { "external_id": "string", "email_hash": "string", "phone_hash": "string" }, "coupon_code": "string", "source": "api", "attribution_method": "click_id", "occurred_at": "2026-12-05T10:15:30.000Z", "attributed_at": "2026-12-05T10:15:30.000Z", "metadata": {}, "created_at": "2026-12-05T10:15:30.000Z" }Example generated from the schema. 401 response
Missing or invalid credentials. Always
code: unauthenticated;details[0].codegives the reason (missing_credentials,invalid_api_key,api_key_revoked,api_key_expired,session_expired,publishable_key_not_allowed).Error codes:
unauthenticatedError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 401 response: unauthenticatedJSON{ "error": { "type": "authentication_error", "code": "unauthenticated", "message": "The API key is not valid.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#unauthenticated", "details": [ { "path": "Authorization", "code": "invalid_api_key", "message": "No key matches this secret" } ] } }404 response
Unknown id, or the resource belongs to another workspace (never distinguished). Also returned when a session's
X-Workspace-Idnames a workspace the user is not an active member of.Error codes:
resource_not_foundError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 404 response: not foundJSON{ "error": { "type": "not_found_error", "code": "resource_not_found", "message": "No link with id lnk_01JB4N8ZK3Q9WXYZ0123456789.", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#resource_not_found" } }409 response
State conflict (
slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use).Error codes:
slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_useError schema and example
Field Type Description errorrequired object error. typerequired string One of: invalid_request_error,authentication_error,permission_error,plan_limit_error,not_found_error,conflict_error,validation_error,rate_limit_error,api_errorerror. coderequired string Complete error-code catalogue. @urlcrop/shared/errorsis tested against this list.paramon plan_limit_error responses is always a plan limit key.One of:invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand,unauthenticated,two_factor_required,step_up_required,email_verification_required,signups_paused,insufficient_scope,insufficient_role,workspace_mismatch,wrong_environment,workspace_suspended,write_blocked_past_due,content_policy_hold,origin_not_allowed,turnstile_failed,second_approver_required,view_as_read_only,support_access_approval_required,feature_not_in_plan,plan_limit_reached,resource_not_found,route_not_found,slug_taken,domain_already_exists,member_already_exists,invitation_pending,idempotency_in_progress,state_conflict,resource_in_use,payload_too_large,unsupported_media_type,validation_failed,destination_invalid,destination_blocked,destination_unreachable,slug_invalid,slug_reserved,domain_not_active,domain_proxied,idempotency_key_reused,unsupported_qr_type,qr_unreadable,invalid_routing_rule,invalid_currency,csv_invalid,attribution_key_missing,policy_acceptance_required,rate_limited,internal_error,upstream_unavailable,service_unavailable,timeouterror. messagerequired string Human-readable, safe to show to end users. error. param string Field, header or scope the error refers to, when applicable. error. request_idrequired string error. doc_urlrequired string Format: uri error. details array of object error. details[]. path string error. details[]. coderequired string Zod issue code, unsupported_in_phase, a destination safety reason, or a 401 reason.error. details[]. messagerequired string error. details[]. limit integer | null Plan limit in force (plan_limit_error only; null = unlimited). error. details[]. used integer Current usage (plan_limit_error only). error. details[]. resets_at string When a periodic limit resets (plan_limit_error only).Format: date-time error. details[]. upgrade_to string Plan slug that lifts a plan limit (plan_limit_error only). 409 response: slug takenJSON{ "error": { "type": "conflict_error", "code": "slug_taken", "message": "The slug \"diwali\" is already in use on crop.sh.", "param": "slug", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#slug_taken" } }