Billing
Billing endpoints of the URLCrop API: 6 operations. Plans, subscription, checkout (Razorpay/PayPal), invoices, usage. All purchases are final.
Current subscription of the organization
GET/billing/subscription
- Scope billing:read
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. |
Request example
curl 'https://api.urlcrop.com/v1/billing/subscription' \
-H 'Authorization: Bearer uc_live_…'Responses
200 response
Subscription
Subscription schema and example
Field Type Description idrequired string objectrequired string Value: subscriptionorganization_idrequired string planrequired string One of: free,starter,pro,business,agency,enterpriseintervalrequired string | null One of: monthly,annual,nullstatusrequired string nonefor a Free organization that never subscribed.One of:none,active,past_due,canceledproviderrequired string One of: none,razorpay,paypal,manualprovider_subscription_id string | null currency string | null amount integer | null current_period_start string | null Format: date-time current_period_end string | null Format: date-time cancel_at_period_endrequired boolean scheduled_change object | null Pending downgrade or interval change applied at period end. scheduled_change. plan string scheduled_change. interval string scheduled_change. effective_at string ISO 8601 UTC with milliseconds.Format: date-time past_due_since string | null Format: date-time payment_failed_at string | null D0 of the current failed renewal; the dashboard shows the payment-failed banner from here. Read-only starts at D7.Format: date-time dunning_stage integer 0 none, 1 day-1 email, 2 day-3, 3 day-7 (read-only), 4 day-30 (Free limits).≥ 0, ≤ 4 read_only boolean True from day 7 of a failed renewal until payment or the day-30 Free fallback; writes answer 403 write_blocked_past_due. Links keep redirecting.staterequired string Derived billing state ( @urlcrop/shared/billingtoBillingView); the dashboard never re-derives it from other fields.One of:free,incomplete,pending_activation,active,past_due,downgraded_to_free,cancelledcurrency_lockedrequired boolean True once a payment was captured or a subscription went live; the billing currency can no longer change. action_requiredrequired null | object A step the Owner must take before due_at(UPI/e-mandate or card re-authorisation, PayPal re-approval, renewal checkout).action_required. typerequired string One of: razorpay_reauth,paypal_approval,renewal_checkoutaction_required. checkout_session_idrequired string | null action_required. approval_urlrequired string | null Format: uri action_required. due_atrequired string ISO 8601 UTC with milliseconds.Format: date-time pending_checkout_session_id string | null The unconfirmed checkout ( cs_…) behind anincompletesubscription, for Try again / Cancel checkout. Null in every other state.payment_methodrequired null | object Non-sensitive label of the authorised instrument ("Visa ending 4242", "UPI AutoPay", "PayPal"); never a VPA or email address. payment_method. typerequired string One of: card,upi,emandate,netbanking,paypal_wallet,paypal_card,unknownpayment_method. labelrequired string max length 60 created_atrequired string ISO 8601 UTC with milliseconds.Format: date-time updated_atrequired string ISO 8601 UTC with milliseconds.Format: date-time 200 response: 200 responseJSON{ "id": "sub_01JB4PK0L1M2N3P4Q5R6S7T8U9", "object": "subscription", "organization_id": "string", "plan": "free", "interval": "monthly", "status": "none", "provider": "none", "provider_subscription_id": "string", "currency": "string", "amount": 0, "current_period_start": "2026-12-05T10:15:30.000Z", "current_period_end": "2026-12-05T10:15:30.000Z", "cancel_at_period_end": false, "scheduled_change": { "plan": "string", "interval": "string", "effective_at": "2026-12-05T10:15:30.000Z" }, "past_due_since": "2026-12-05T10:15:30.000Z", "payment_failed_at": "2026-12-05T10:15:30.000Z", "dunning_stage": 0, "read_only": false, "state": "free", "currency_locked": false, "action_required": { "type": "razorpay_reauth", "checkout_session_id": "string", "approval_url": "https://example.com", "due_at": "2026-12-05T10:15:30.000Z" }, "pending_checkout_session_id": "string", "payment_method": { "type": "card", "label": "string" }, "created_at": "2026-12-05T10:15:30.000Z", "updated_at": "2026-12-05T10:15:30.000Z" }Example generated from the schema. 400 response
Malformed request (
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand). Any credentialed operation can return it: a credential in the query string (api_key,access_token) isinvalid_query, and a session request withoutX-Workspace-Idon a workspace-scoped route ismissing_header.Error codes:
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expandError 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). 400 response: missing headerJSON{ "error": { "type": "invalid_request_error", "code": "missing_header", "message": "The X-Workspace-Id header is required for session requests.", "param": "X-Workspace-Id", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#missing_header" } }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" } }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" } }
List invoices
GET/billing/invoices
- Scope billing:read
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). |
| status | query | string | One of: issued, paid, partially_paid, void, uncollectible, corrected |
| from | query | string | Start of the period (inclusive). YYYY-MM-DD or RFC 3339. Default 30 days ago. |
| to | query | string | End of the period (inclusive). Default now. |
Request example
curl 'https://api.urlcrop.com/v1/billing/invoices' \
-H 'Authorization: Bearer uc_live_…'Responses
200 response
Invoices
InvoiceList schema and example
Field Type Description datarequired array of Invoice data[]. idrequired string data[]. objectrequired string Value: invoicedata[]. numberrequired string Sequential per Indian financial year; never reused. data[]. organization_idrequired string data[]. statusrequired string correctedfollows a staff-only correction of a duplicate charge caused by a system error, or a lost dispute; a credit note is attached.voidonly before any payment. There is norefundedstatus.One of:draft,issued,paid,partially_paid,void,uncollectible,correcteddata[]. sourcerequired string One of: subscription,upgrade_difference,pack,addon_difference,manual,correctiondata[]. descriptionrequired string Row label such as "Starter monthly". data[]. supply_type string One of: intra_state,inter_state,export_lutdata[]. credit_notes array of object data[]. credit_notes[]. idrequired string data[]. credit_notes[]. numberrequired string data[]. credit_notes[]. reasonrequired string One of: system_error_duplicate,provider_dispute,invoice_errordata[]. credit_notes[]. totalrequired integer data[]. credit_notes[]. issued_atrequired string ISO 8601 UTC with milliseconds.Format: date-time data[]. currencyrequired string One of: INR,USDdata[]. subtotalrequired integer data[]. tax_totalrequired integer data[]. totalrequired integer data[]. amount_paidrequired integer data[]. amount_duerequired integer data[]. billing_country string data[]. gstin string | null data[]. tax_linesrequired array of object data[]. tax_lines[]. typerequired string One of: CGST,SGST,IGST,NONEdata[]. tax_lines[]. rate_bpsrequired integer Basis points (900 = 9 %). data[]. tax_lines[]. amountrequired integer data[]. linesrequired array of object data[]. lines[]. idrequired string data[]. lines[]. descriptionrequired string data[]. lines[]. quantityrequired integer data[]. lines[]. unit_amountrequired integer data[]. lines[]. amountrequired integer data[]. lines[]. period object data[]. period_start string | null Format: date-time data[]. period_end string | null Format: date-time data[]. policy_acceptance PolicyAcceptance | null data[]. policy_acceptance. policy_versionrequired string data[]. policy_acceptance. accepted_atrequired string ISO 8601 UTC with milliseconds.Format: date-time data[]. policy_acceptance. accepted_by string User id. data[]. policy_acceptance. ip_country string | null Country of the accepting request. The IP itself is stored only as a keyed hash and never returned. data[]. payment_id string | null data[]. issued_atrequired string ISO 8601 UTC with milliseconds.Format: date-time data[]. due_at string | null Format: date-time data[]. paid_at string | null Format: date-time 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": "inv_01JB4PM2N3P4Q5R6S7T8U9V0W1", "object": "invoice", "number": "UC/26-27/000123", "organization_id": "string", "status": "draft", "source": "subscription", "description": "string", "supply_type": "intra_state", "credit_notes": [ { "id": "string", "number": "CN/26-27/000001", "reason": "system_error_duplicate", "total": 0, "issued_at": "2026-12-05T10:15:30.000Z" } ], "currency": "INR", "subtotal": 0, "tax_total": 0, "total": 0, "amount_paid": 0, "amount_due": 0, "billing_country": "string", "gstin": "string", "tax_lines": [ { "type": "CGST", "rate_bps": 0, "amount": 0 } ], "lines": [ { "id": "string", "description": "string", "quantity": 0, "unit_amount": 0, "amount": 0, "period": { "start": null, "end": null } } ], "period_start": "2026-12-05T10:15:30.000Z", "period_end": "2026-12-05T10:15:30.000Z", "policy_acceptance": { "policy_version": "string", "accepted_at": "2026-12-05T10:15:30.000Z", "accepted_by": "string", "ip_country": "string" }, "payment_id": "string", "issued_at": "2026-12-05T10:15:30.000Z", "due_at": "2026-12-05T10:15:30.000Z", "paid_at": "2026-12-05T10:15:30.000Z", "created_at": "2026-12-05T10:15:30.000Z" } ], "pagination": { "limit": 0, "has_more": false, "next_cursor": "string", "total": 0 } }Example generated from the schema. 400 response
Malformed request (
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand). Any credentialed operation can return it: a credential in the query string (api_key,access_token) isinvalid_query, and a session request withoutX-Workspace-Idon a workspace-scoped route ismissing_header.Error codes:
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expandError 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). 400 response: missing headerJSON{ "error": { "type": "invalid_request_error", "code": "missing_header", "message": "The X-Workspace-Id header is required for session requests.", "param": "X-Workspace-Id", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#missing_header" } }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" } }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" } }
Get an invoice
GET/billing/invoices/{id}
- Scope billing:read
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/billing/invoices/lnk_01JB4N8ZK3Q9WXYZ0123456789' \
-H 'Authorization: Bearer uc_live_…'Responses
200 response
Invoice
Invoice schema and example
Field Type Description idrequired string objectrequired string Value: invoicenumberrequired string Sequential per Indian financial year; never reused. organization_idrequired string statusrequired string correctedfollows a staff-only correction of a duplicate charge caused by a system error, or a lost dispute; a credit note is attached.voidonly before any payment. There is norefundedstatus.One of:draft,issued,paid,partially_paid,void,uncollectible,correctedsourcerequired string One of: subscription,upgrade_difference,pack,addon_difference,manual,correctiondescriptionrequired string Row label such as "Starter monthly". supply_type string One of: intra_state,inter_state,export_lutcredit_notes array of object credit_notes[]. idrequired string credit_notes[]. numberrequired string credit_notes[]. reasonrequired string One of: system_error_duplicate,provider_dispute,invoice_errorcredit_notes[]. totalrequired integer credit_notes[]. issued_atrequired string ISO 8601 UTC with milliseconds.Format: date-time currencyrequired string One of: INR,USDsubtotalrequired integer tax_totalrequired integer totalrequired integer amount_paidrequired integer amount_duerequired integer billing_country string gstin string | null tax_linesrequired array of object tax_lines[]. typerequired string One of: CGST,SGST,IGST,NONEtax_lines[]. rate_bpsrequired integer Basis points (900 = 9 %). tax_lines[]. amountrequired integer linesrequired array of object lines[]. idrequired string lines[]. descriptionrequired string lines[]. quantityrequired integer lines[]. unit_amountrequired integer lines[]. amountrequired integer lines[]. period object lines[]. period. start string ISO 8601 UTC with milliseconds.Format: date-time lines[]. period. end string ISO 8601 UTC with milliseconds.Format: date-time period_start string | null Format: date-time period_end string | null Format: date-time policy_acceptance PolicyAcceptance | null policy_acceptance. policy_versionrequired string policy_acceptance. accepted_atrequired string ISO 8601 UTC with milliseconds.Format: date-time policy_acceptance. accepted_by string User id. policy_acceptance. ip_country string | null Country of the accepting request. The IP itself is stored only as a keyed hash and never returned. payment_id string | null issued_atrequired string ISO 8601 UTC with milliseconds.Format: date-time due_at string | null Format: date-time paid_at string | null Format: date-time created_atrequired string ISO 8601 UTC with milliseconds.Format: date-time 200 response: 200 responseJSON{ "id": "inv_01JB4PM2N3P4Q5R6S7T8U9V0W1", "object": "invoice", "number": "UC/26-27/000123", "organization_id": "string", "status": "draft", "source": "subscription", "description": "string", "supply_type": "intra_state", "credit_notes": [ { "id": "string", "number": "CN/26-27/000001", "reason": "system_error_duplicate", "total": 0, "issued_at": "2026-12-05T10:15:30.000Z" } ], "currency": "INR", "subtotal": 0, "tax_total": 0, "total": 0, "amount_paid": 0, "amount_due": 0, "billing_country": "string", "gstin": "string", "tax_lines": [ { "type": "CGST", "rate_bps": 0, "amount": 0 } ], "lines": [ { "id": "string", "description": "string", "quantity": 0, "unit_amount": 0, "amount": 0, "period": { "start": "2026-12-05T10:15:30.000Z", "end": "2026-12-05T10:15:30.000Z" } } ], "period_start": "2026-12-05T10:15:30.000Z", "period_end": "2026-12-05T10:15:30.000Z", "policy_acceptance": { "policy_version": "string", "accepted_at": "2026-12-05T10:15:30.000Z", "accepted_by": "string", "ip_country": "string" }, "payment_id": "string", "issued_at": "2026-12-05T10:15:30.000Z", "due_at": "2026-12-05T10:15:30.000Z", "paid_at": "2026-12-05T10:15:30.000Z", "created_at": "2026-12-05T10:15:30.000Z" }Example generated from the schema. 400 response
Malformed request (
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand). Any credentialed operation can return it: a credential in the query string (api_key,access_token) isinvalid_query, and a session request withoutX-Workspace-Idon a workspace-scoped route ismissing_header.Error codes:
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expandError 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). 400 response: missing headerJSON{ "error": { "type": "invalid_request_error", "code": "missing_header", "message": "The X-Workspace-Id header is required for session requests.", "param": "X-Workspace-Id", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#missing_header" } }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" } }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" } }
Invoice PDF
GET/billing/invoices/{id}/pdf
- Scope billing:read
Redirects to a signed file URL (15 minutes) unless inline=true, which streams the PDF. While the PDF is still being rendered after issuance: 409 state_conflict with Retry-After.
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. |
| inline | query | boolean |
Request example
curl 'https://api.urlcrop.com/v1/billing/invoices/lnk_01JB4N8ZK3Q9WXYZ0123456789/pdf' \
-H 'Authorization: Bearer uc_live_…'Responses
200 response
PDF (inline)
Body schema and example
200 response: 200 responseJSON"string"Example generated from the schema. 302 response
Redirect to the signed file URL
400 response
Malformed request (
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand). Any credentialed operation can return it: a credential in the query string (api_key,access_token) isinvalid_query, and a session request withoutX-Workspace-Idon a workspace-scoped route ismissing_header.Error codes:
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expandError 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). 400 response: missing headerJSON{ "error": { "type": "invalid_request_error", "code": "missing_header", "message": "The X-Workspace-Id header is required for session requests.", "param": "X-Workspace-Id", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#missing_header" } }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" } }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" } }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" } }
Billing details (legal name, GSTIN, address)
GET/billing/customer
- Scope billing:read
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. |
Request example
curl 'https://api.urlcrop.com/v1/billing/customer' \
-H 'Authorization: Bearer uc_live_…'Responses
200 response
Customer
BillingCustomer schema and example
Field Type Description legal_namerequired string max length 200 emailrequired string Format: email gstin string | null address object address. line1 string address. line2 string address. city string address. state string address. state_code string Indian GST state code (e.g. 24 for Gujarat). address. postal_code string address. country string billing_countryrequired string tax_status string Derived by the server from the country and GSTIN; ignored on write.One of: b2b_registered,b2c_unregistered,export,sez200 response: 200 responseJSON{ "legal_name": "string", "email": "name@example.com", "gstin": "string", "address": { "line1": "string", "line2": "string", "city": "string", "state": "string", "state_code": "string", "postal_code": "string", "country": "string" }, "billing_country": "string", "tax_status": "b2b_registered" }Example generated from the schema. 400 response
Malformed request (
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand). Any credentialed operation can return it: a credential in the query string (api_key,access_token) isinvalid_query, and a session request withoutX-Workspace-Idon a workspace-scoped route ismissing_header.Error codes:
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expandError 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). 400 response: missing headerJSON{ "error": { "type": "invalid_request_error", "code": "missing_header", "message": "The X-Workspace-Id header is required for session requests.", "param": "X-Workspace-Id", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#missing_header" } }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" } }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" } }
Payment attempts
GET/billing/payments
- Scope billing:read
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). |
Request example
curl 'https://api.urlcrop.com/v1/billing/payments' \
-H 'Authorization: Bearer uc_live_…'Responses
200 response
Payments
PaymentList schema and example
Field Type Description datarequired array of Payment data[]. idrequired string data[]. objectrequired string Value: paymentdata[]. invoice_idrequired string data[]. providerrequired string One of: razorpay,paypal,manualdata[]. provider_payment_id string | null data[]. statusrequired string One of: pending,succeeded,faileddata[]. amountrequired Money data[]. amount. amountrequired integer Integer minor units (paise, cents). Never a float. data[]. amount. currencyrequired string ISO 4217 code.One of: INR,USDdata[]. method string | null data[]. failure_reason string | null data[]. attempted_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": "pay_01JB4PN3P4Q5R6S7T8U9V0W1X2", "object": "payment", "invoice_id": "string", "provider": "razorpay", "provider_payment_id": "string", "status": "pending", "amount": { "amount": 149900, "currency": "INR" }, "method": "upi", "failure_reason": "string", "attempted_at": "2026-12-05T10:15:30.000Z" } ], "pagination": { "limit": 0, "has_more": false, "next_cursor": "string", "total": 0 } }Example generated from the schema. 400 response
Malformed request (
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expand). Any credentialed operation can return it: a credential in the query string (api_key,access_token) isinvalid_query, and a session request withoutX-Workspace-Idon a workspace-scoped route ismissing_header.Error codes:
invalid_json,invalid_query,missing_header,invalid_cursor,invalid_sort,invalid_expandError 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). 400 response: missing headerJSON{ "error": { "type": "invalid_request_error", "code": "missing_header", "message": "The X-Workspace-Id header is required for session requests.", "param": "X-Workspace-Id", "request_id": "req_01JB4N8ZK3Q9WXYZ0123456789", "doc_url": "https://urlcrop.com/docs/api/errors#missing_header" } }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" } }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" } }