[{"data":1,"prerenderedAt":1805},["ShallowReactive",2],{"navigation_docs":3,"-packages-django-testing":465,"-packages-django-testing-surround":1800},[4,8,62,115,450],{"title":5,"path":6,"stem":7},"Introduction","\u002Fintroduction","0.introduction",{"title":9,"path":10,"stem":11,"children":12,"page":61},"Guides","\u002Fguides","1.guides",[13,17,21,25,29,33,37,41,45,49,53,57],{"title":14,"path":15,"stem":16},"Quickstart","\u002Fguides\u002Fquickstart","1.guides\u002F1.quickstart",{"title":18,"path":19,"stem":20},"Payouts & Settlement","\u002Fguides\u002Fpayouts","1.guides\u002F10.payouts",{"title":22,"path":23,"stem":24},"Customer Emails","\u002Fguides\u002Fcustomer-emails","1.guides\u002F11.customer-emails",{"title":26,"path":27,"stem":28},"Build your own integration","\u002Fguides\u002Fbuild-your-own-integration","1.guides\u002F2.build-your-own-integration",{"title":30,"path":31,"stem":32},"Selling Workflow","\u002Fguides\u002Fselling-workflow","1.guides\u002F2.selling-workflow",{"title":34,"path":35,"stem":36},"Vatly SDKs","\u002Fguides\u002Fsdks","1.guides\u002F3.sdks",{"title":38,"path":39,"stem":40},"Authentication","\u002Fguides\u002Fauthentication","1.guides\u002F4.authentication",{"title":42,"path":43,"stem":44},"Pagination","\u002Fguides\u002Fpagination","1.guides\u002F5.pagination",{"title":46,"path":47,"stem":48},"Errors","\u002Fguides\u002Ferrors","1.guides\u002F6.errors",{"title":50,"path":51,"stem":52},"Webhooks","\u002Fguides\u002Fwebhooks","1.guides\u002F7.webhooks",{"title":54,"path":55,"stem":56},"Idempotency","\u002Fguides\u002Fidempotency","1.guides\u002F8.idempotency",{"title":58,"path":59,"stem":60},"Testing","\u002Fguides\u002Ftesting","1.guides\u002F9.testing",false,{"title":63,"path":64,"stem":65,"children":66,"page":61},"Api Reference","\u002Fapi-reference","2.api-reference",[67,71,75,79,83,87,91,95,99,103,107,111],{"title":68,"path":69,"stem":70},"Customers","\u002Fapi-reference\u002Fcustomers","2.api-reference\u002F1.customers",{"title":72,"path":73,"stem":74},"Webhook Endpoints","\u002Fapi-reference\u002Fwebhook-endpoints","2.api-reference\u002F10.webhook-endpoints",{"title":76,"path":77,"stem":78},"Test helpers","\u002Fapi-reference\u002Ftest-helpers","2.api-reference\u002F11.test-helpers",{"title":80,"path":81,"stem":82},"Checkouts","\u002Fapi-reference\u002Fcheckouts","2.api-reference\u002F2.checkouts",{"title":84,"path":85,"stem":86},"One-off Products","\u002Fapi-reference\u002Fone-off-products","2.api-reference\u002F3.one-off-products",{"title":88,"path":89,"stem":90},"Subscriptions","\u002Fapi-reference\u002Fsubscriptions","2.api-reference\u002F4.subscriptions",{"title":92,"path":93,"stem":94},"Subscription Plans","\u002Fapi-reference\u002Fsubscription-plans","2.api-reference\u002F5.subscription-plans",{"title":96,"path":97,"stem":98},"Orders","\u002Fapi-reference\u002Forders","2.api-reference\u002F6.orders",{"title":100,"path":101,"stem":102},"Order Refunds","\u002Fapi-reference\u002Frefunds","2.api-reference\u002F7.refunds",{"title":104,"path":105,"stem":106},"Refunds","\u002Fapi-reference\u002Fglobal-refunds","2.api-reference\u002F8.global-refunds",{"title":108,"path":109,"stem":110},"Chargebacks","\u002Fapi-reference\u002Fchargebacks","2.api-reference\u002F9.chargebacks",{"title":112,"path":113,"stem":114},"Webhook Events","\u002Fapi-reference\u002Fwebhook-events","2.api-reference\u002F99.webhook-events",{"title":116,"path":117,"stem":118,"children":119},"Packages","\u002Fpackages","3.packages",[120,122,164,210,244,283,318,366,408],{"title":116,"path":117,"stem":121},"3.packages\u002Findex",{"title":123,"path":124,"stem":125,"children":126,"page":61},"PHP SDK","\u002Fpackages\u002Fphp","3.packages\u002F1.php",[127,131,134,137,140,144,147,151,154,157,160],{"title":128,"path":129,"stem":130},"Getting started","\u002Fpackages\u002Fphp\u002Freadme","3.packages\u002F1.php\u002F00.readme",{"title":68,"path":132,"stem":133},"\u002Fpackages\u002Fphp\u002Fcustomers","3.packages\u002F1.php\u002F02.customers",{"title":80,"path":135,"stem":136},"\u002Fpackages\u002Fphp\u002Fcheckouts","3.packages\u002F1.php\u002F03.checkouts",{"title":88,"path":138,"stem":139},"\u002Fpackages\u002Fphp\u002Fsubscriptions","3.packages\u002F1.php\u002F04.subscriptions",{"title":141,"path":142,"stem":143},"Subscription plans","\u002Fpackages\u002Fphp\u002Fsubscriptionplans","3.packages\u002F1.php\u002F05.subscriptionplans",{"title":96,"path":145,"stem":146},"\u002Fpackages\u002Fphp\u002Forders","3.packages\u002F1.php\u002F06.orders",{"title":148,"path":149,"stem":150},"One-off products","\u002Fpackages\u002Fphp\u002Foneoffproducts","3.packages\u002F1.php\u002F07.oneoffproducts",{"title":104,"path":152,"stem":153},"\u002Fpackages\u002Fphp\u002Frefunds","3.packages\u002F1.php\u002F08.refunds",{"title":108,"path":155,"stem":156},"\u002Fpackages\u002Fphp\u002Fchargebacks","3.packages\u002F1.php\u002F09.chargebacks",{"title":50,"path":158,"stem":159},"\u002Fpackages\u002Fphp\u002Fwebhooks","3.packages\u002F1.php\u002F10.webhooks",{"title":161,"path":162,"stem":163},"Webhook URLs","\u002Fpackages\u002Fphp\u002Fwebhookendpoints","3.packages\u002F1.php\u002F11.webhookendpoints",{"title":165,"path":166,"stem":167,"children":168,"page":61},"PHP Fluent","\u002Fpackages\u002Ffluent-php","3.packages\u002F2.fluent-php",[169,172,176,180,183,186,189,192,196,199,203,207],{"title":128,"path":170,"stem":171},"\u002Fpackages\u002Ffluent-php\u002Freadme","3.packages\u002F2.fluent-php\u002F00.readme",{"title":173,"path":174,"stem":175},"Configuration","\u002Fpackages\u002Ffluent-php\u002Fconfiguration","3.packages\u002F2.fluent-php\u002F01.configuration",{"title":177,"path":178,"stem":179},"Core concepts","\u002Fpackages\u002Ffluent-php\u002Fcoreconcepts","3.packages\u002F2.fluent-php\u002F02.coreconcepts",{"title":68,"path":181,"stem":182},"\u002Fpackages\u002Ffluent-php\u002Fcustomers","3.packages\u002F2.fluent-php\u002F03.customers",{"title":80,"path":184,"stem":185},"\u002Fpackages\u002Ffluent-php\u002Fcheckouts","3.packages\u002F2.fluent-php\u002F04.checkouts",{"title":88,"path":187,"stem":188},"\u002Fpackages\u002Ffluent-php\u002Fsubscriptions","3.packages\u002F2.fluent-php\u002F05.subscriptions",{"title":96,"path":190,"stem":191},"\u002Fpackages\u002Ffluent-php\u002Forders","3.packages\u002F2.fluent-php\u002F06.orders",{"title":193,"path":194,"stem":195},"Customer portal","\u002Fpackages\u002Ffluent-php\u002Fcustomerportal","3.packages\u002F2.fluent-php\u002F07.customerportal",{"title":50,"path":197,"stem":198},"\u002Fpackages\u002Ffluent-php\u002Fwebhooks","3.packages\u002F2.fluent-php\u002F08.webhooks",{"title":200,"path":201,"stem":202},"Webhook event flow","\u002Fpackages\u002Ffluent-php\u002Fwebhook-flow","3.packages\u002F2.fluent-php\u002F09.webhook-flow",{"title":204,"path":205,"stem":206},"Existing tables","\u002Fpackages\u002Ffluent-php\u002Fhost-owns-its-tables","3.packages\u002F2.fluent-php\u002F10.host-owns-its-tables",{"title":58,"path":208,"stem":209},"\u002Fpackages\u002Ffluent-php\u002Ftesting","3.packages\u002F2.fluent-php\u002F11.testing",{"title":211,"path":212,"stem":213,"children":214,"page":61},"Laravel","\u002Fpackages\u002Flaravel","3.packages\u002F3.laravel",[215,218,221,224,227,230,233,236,240],{"title":128,"path":216,"stem":217},"\u002Fpackages\u002Flaravel\u002Freadme","3.packages\u002F3.laravel\u002F00.readme",{"title":173,"path":219,"stem":220},"\u002Fpackages\u002Flaravel\u002Fconfiguration","3.packages\u002F3.laravel\u002F01.configuration",{"title":68,"path":222,"stem":223},"\u002Fpackages\u002Flaravel\u002Fcustomers","3.packages\u002F3.laravel\u002F02.customers",{"title":80,"path":225,"stem":226},"\u002Fpackages\u002Flaravel\u002Fcheckouts","3.packages\u002F3.laravel\u002F03.checkouts",{"title":88,"path":228,"stem":229},"\u002Fpackages\u002Flaravel\u002Fsubscriptions","3.packages\u002F3.laravel\u002F04.subscriptions",{"title":96,"path":231,"stem":232},"\u002Fpackages\u002Flaravel\u002Forders","3.packages\u002F3.laravel\u002F05.orders",{"title":50,"path":234,"stem":235},"\u002Fpackages\u002Flaravel\u002Fwebhooks","3.packages\u002F3.laravel\u002F06.webhooks",{"title":237,"path":238,"stem":239},"Comparison","\u002Fpackages\u002Flaravel\u002Fcomparison","3.packages\u002F3.laravel\u002F07.comparison",{"title":241,"path":242,"stem":243},"Migrating from Cashier","\u002Fpackages\u002Flaravel\u002Fmigrating-to-vatly","3.packages\u002F3.laravel\u002F08.migrating-to-vatly",{"title":245,"path":246,"stem":247,"children":248,"page":61},"JavaScript SDK","\u002Fpackages\u002Fjavascript","3.packages\u002F4.javascript",[249,252,255,258,261,264,267,270,273,276,279],{"title":128,"path":250,"stem":251},"\u002Fpackages\u002Fjavascript\u002Freadme","3.packages\u002F4.javascript\u002F00.readme",{"title":68,"path":253,"stem":254},"\u002Fpackages\u002Fjavascript\u002Fcustomers","3.packages\u002F4.javascript\u002F02.customers",{"title":80,"path":256,"stem":257},"\u002Fpackages\u002Fjavascript\u002Fcheckouts","3.packages\u002F4.javascript\u002F03.checkouts",{"title":88,"path":259,"stem":260},"\u002Fpackages\u002Fjavascript\u002Fsubscriptions","3.packages\u002F4.javascript\u002F04.subscriptions",{"title":141,"path":262,"stem":263},"\u002Fpackages\u002Fjavascript\u002Fsubscriptionplans","3.packages\u002F4.javascript\u002F05.subscriptionplans",{"title":96,"path":265,"stem":266},"\u002Fpackages\u002Fjavascript\u002Forders","3.packages\u002F4.javascript\u002F06.orders",{"title":148,"path":268,"stem":269},"\u002Fpackages\u002Fjavascript\u002Foneoffproducts","3.packages\u002F4.javascript\u002F07.oneoffproducts",{"title":104,"path":271,"stem":272},"\u002Fpackages\u002Fjavascript\u002Frefunds","3.packages\u002F4.javascript\u002F08.refunds",{"title":108,"path":274,"stem":275},"\u002Fpackages\u002Fjavascript\u002Fchargebacks","3.packages\u002F4.javascript\u002F09.chargebacks",{"title":50,"path":277,"stem":278},"\u002Fpackages\u002Fjavascript\u002Fwebhooks","3.packages\u002F4.javascript\u002F10.webhooks",{"title":280,"path":281,"stem":282},"API reference","\u002Fpackages\u002Fjavascript\u002Fapi","3.packages\u002F4.javascript\u002F12.api",{"title":284,"path":285,"stem":286,"children":287,"page":61},"JavaScript Fluent","\u002Fpackages\u002Ffluent-js","3.packages\u002F5.fluent-js",[288,291,294,297,300,303,306,309,312,315],{"title":128,"path":289,"stem":290},"\u002Fpackages\u002Ffluent-js\u002Freadme","3.packages\u002F5.fluent-js\u002F00.readme",{"title":173,"path":292,"stem":293},"\u002Fpackages\u002Ffluent-js\u002Fconfiguration","3.packages\u002F5.fluent-js\u002F01.configuration",{"title":177,"path":295,"stem":296},"\u002Fpackages\u002Ffluent-js\u002Fcoreconcepts","3.packages\u002F5.fluent-js\u002F02.coreconcepts",{"title":68,"path":298,"stem":299},"\u002Fpackages\u002Ffluent-js\u002Fcustomers","3.packages\u002F5.fluent-js\u002F03.customers",{"title":80,"path":301,"stem":302},"\u002Fpackages\u002Ffluent-js\u002Fcheckouts","3.packages\u002F5.fluent-js\u002F04.checkouts",{"title":88,"path":304,"stem":305},"\u002Fpackages\u002Ffluent-js\u002Fsubscriptions","3.packages\u002F5.fluent-js\u002F05.subscriptions",{"title":96,"path":307,"stem":308},"\u002Fpackages\u002Ffluent-js\u002Forders","3.packages\u002F5.fluent-js\u002F06.orders",{"title":193,"path":310,"stem":311},"\u002Fpackages\u002Ffluent-js\u002Fcustomerportal","3.packages\u002F5.fluent-js\u002F07.customerportal",{"title":50,"path":313,"stem":314},"\u002Fpackages\u002Ffluent-js\u002Fwebhooks","3.packages\u002F5.fluent-js\u002F08.webhooks",{"title":58,"path":316,"stem":317},"\u002Fpackages\u002Ffluent-js\u002Ftesting","3.packages\u002F5.fluent-js\u002F11.testing",{"title":319,"path":320,"stem":321,"children":322,"page":61},"Python SDK","\u002Fpackages\u002Fpython","3.packages\u002F6.python",[323,326,329,332,335,338,341,344,347,350,353,356,359,362],{"title":128,"path":324,"stem":325},"\u002Fpackages\u002Fpython\u002Freadme","3.packages\u002F6.python\u002F00.readme",{"title":173,"path":327,"stem":328},"\u002Fpackages\u002Fpython\u002Fconfiguration","3.packages\u002F6.python\u002F01.configuration",{"title":68,"path":330,"stem":331},"\u002Fpackages\u002Fpython\u002Fcustomers","3.packages\u002F6.python\u002F02.customers",{"title":80,"path":333,"stem":334},"\u002Fpackages\u002Fpython\u002Fcheckouts","3.packages\u002F6.python\u002F03.checkouts",{"title":88,"path":336,"stem":337},"\u002Fpackages\u002Fpython\u002Fsubscriptions","3.packages\u002F6.python\u002F04.subscriptions",{"title":141,"path":339,"stem":340},"\u002Fpackages\u002Fpython\u002Fsubscriptionplans","3.packages\u002F6.python\u002F05.subscriptionplans",{"title":96,"path":342,"stem":343},"\u002Fpackages\u002Fpython\u002Forders","3.packages\u002F6.python\u002F06.orders",{"title":148,"path":345,"stem":346},"\u002Fpackages\u002Fpython\u002Foneoffproducts","3.packages\u002F6.python\u002F07.oneoffproducts",{"title":104,"path":348,"stem":349},"\u002Fpackages\u002Fpython\u002Frefunds","3.packages\u002F6.python\u002F08.refunds",{"title":108,"path":351,"stem":352},"\u002Fpackages\u002Fpython\u002Fchargebacks","3.packages\u002F6.python\u002F09.chargebacks",{"title":50,"path":354,"stem":355},"\u002Fpackages\u002Fpython\u002Fwebhooks","3.packages\u002F6.python\u002F10.webhooks",{"title":161,"path":357,"stem":358},"\u002Fpackages\u002Fpython\u002Fwebhookendpoints","3.packages\u002F6.python\u002F11.webhookendpoints",{"title":280,"path":360,"stem":361},"\u002Fpackages\u002Fpython\u002Fapi","3.packages\u002F6.python\u002F12.api",{"title":363,"path":364,"stem":365},"Development","\u002Fpackages\u002Fpython\u002Fdevelopment","3.packages\u002F6.python\u002F13.development",{"title":367,"path":368,"stem":369,"children":370,"page":61},"Python Fluent","\u002Fpackages\u002Ffluent-python","3.packages\u002F7.fluent-python",[371,374,377,380,383,386,389,392,395,398,401,405],{"title":128,"path":372,"stem":373},"\u002Fpackages\u002Ffluent-python\u002Freadme","3.packages\u002F7.fluent-python\u002F00.readme",{"title":173,"path":375,"stem":376},"\u002Fpackages\u002Ffluent-python\u002Fconfiguration","3.packages\u002F7.fluent-python\u002F01.configuration",{"title":177,"path":378,"stem":379},"\u002Fpackages\u002Ffluent-python\u002Fcoreconcepts","3.packages\u002F7.fluent-python\u002F02.coreconcepts",{"title":68,"path":381,"stem":382},"\u002Fpackages\u002Ffluent-python\u002Fcustomers","3.packages\u002F7.fluent-python\u002F03.customers",{"title":80,"path":384,"stem":385},"\u002Fpackages\u002Ffluent-python\u002Fcheckouts","3.packages\u002F7.fluent-python\u002F04.checkouts",{"title":88,"path":387,"stem":388},"\u002Fpackages\u002Ffluent-python\u002Fsubscriptions","3.packages\u002F7.fluent-python\u002F05.subscriptions",{"title":96,"path":390,"stem":391},"\u002Fpackages\u002Ffluent-python\u002Forders","3.packages\u002F7.fluent-python\u002F06.orders",{"title":193,"path":393,"stem":394},"\u002Fpackages\u002Ffluent-python\u002Fcustomerportal","3.packages\u002F7.fluent-python\u002F07.customerportal",{"title":50,"path":396,"stem":397},"\u002Fpackages\u002Ffluent-python\u002Fwebhooks","3.packages\u002F7.fluent-python\u002F08.webhooks",{"title":58,"path":399,"stem":400},"\u002Fpackages\u002Ffluent-python\u002Ftesting","3.packages\u002F7.fluent-python\u002F11.testing",{"title":402,"path":403,"stem":404},"Porting","\u002Fpackages\u002Ffluent-python\u002Fporting","3.packages\u002F7.fluent-python\u002F12.porting",{"title":363,"path":406,"stem":407},"\u002Fpackages\u002Ffluent-python\u002Fdevelopment","3.packages\u002F7.fluent-python\u002F13.development",{"title":409,"path":410,"stem":411,"children":412,"page":61},"Django","\u002Fpackages\u002Fdjango","3.packages\u002F8.django",[413,416,420,423,427,431,434,437,440,444,447],{"title":128,"path":414,"stem":415},"\u002Fpackages\u002Fdjango\u002Freadme","3.packages\u002F8.django\u002F00.readme",{"title":417,"path":418,"stem":419},"Installation","\u002Fpackages\u002Fdjango\u002Finstallation","3.packages\u002F8.django\u002F01.installation",{"title":173,"path":421,"stem":422},"\u002Fpackages\u002Fdjango\u002Fconfiguration","3.packages\u002F8.django\u002F02.configuration",{"title":424,"path":425,"stem":426},"Billable models","\u002Fpackages\u002Fdjango\u002Fbillablemodels","3.packages\u002F8.django\u002F03.billablemodels",{"title":428,"path":429,"stem":430},"Checkout","\u002Fpackages\u002Fdjango\u002Fcheckout","3.packages\u002F8.django\u002F04.checkout",{"title":88,"path":432,"stem":433},"\u002Fpackages\u002Fdjango\u002Fbilling","3.packages\u002F8.django\u002F05.billing",{"title":193,"path":435,"stem":436},"\u002Fpackages\u002Fdjango\u002Fcustomerportal","3.packages\u002F8.django\u002F06.customerportal",{"title":50,"path":438,"stem":439},"\u002Fpackages\u002Fdjango\u002Fwebhooks","3.packages\u002F8.django\u002F07.webhooks",{"title":441,"path":442,"stem":443},"Admin","\u002Fpackages\u002Fdjango\u002Fadmin","3.packages\u002F8.django\u002F08.admin",{"title":58,"path":445,"stem":446},"\u002Fpackages\u002Fdjango\u002Ftesting","3.packages\u002F8.django\u002F09.testing",{"title":363,"path":448,"stem":449},"\u002Fpackages\u002Fdjango\u002Fdevelopment","3.packages\u002F8.django\u002F10.development",{"title":451,"path":452,"stem":453,"children":454},"Integrations","\u002Fintegrations","4.integrations",[455,457,461],{"title":451,"path":452,"stem":456},"4.integrations\u002Findex",{"title":458,"path":459,"stem":460},"Lovable payments with Vatly","\u002Fintegrations\u002Flovable","4.integrations\u002F1.lovable",{"title":462,"path":463,"stem":464},"Bolt payments with Vatly","\u002Fintegrations\u002Fbolt","4.integrations\u002F2.bolt",{"id":466,"title":467,"body":468,"description":1793,"extension":1794,"links":1795,"meta":1796,"navigation":1797,"path":445,"seo":1798,"stem":446,"__hash__":1799},"docs\u002F3.packages\u002F8.django\u002F09.testing.md","Test billing offline",{"type":469,"value":470,"toc":1789},"minimark",[471,480,485,1111,1114,1118,1767,1774,1785],[472,473,474,475,479],"p",{},"Use Django's test database and httpx fixtures. Do not use a real Vatly key in unit\ntests. The snippets below are helpers for your pytest-django tests. Call them from\na test marked ",[476,477,478],"code",{},"@pytest.mark.django_db(transaction=True)"," with your project configured.",[481,482,484],"h2",{"id":483},"read-a-customer-with-mocktransport","Read a customer with MockTransport",[486,487,492],"pre",{"className":488,"code":489,"language":490,"meta":491,"style":491},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import httpx\nfrom asgiref.sync import async_to_sync\nfrom vatly import AsyncVatlyClient\nfrom vatly_fluent import Vatly, Wiring\n\n\ndef example():\n    def respond(request):\n        assert request.url.path == \"\u002Fv1\u002Fcustomers\u002Fcustomer_example\"\n        return httpx.Response(\n            200,\n            json={\n                \"id\": \"customer_example\",\n                \"resource\": \"customer\",\n                \"testmode\": True,\n                \"email\": \"buyer@example.com\",\n                \"name\": \"Alex\",\n                \"metadata\": {},\n                \"createdAt\": \"2026-01-01T00:00:00Z\",\n                \"links\": {\n                    \"self\": {\n                        \"href\": \"https:\u002F\u002Fapi.vatly.com\u002Fv1\u002Fcustomers\u002Fcustomer_example\",\n                        \"type\": \"application\u002Fjson\",\n                    }\n                },\n            },\n        )\n\n    async def read_customer():\n        async with AsyncVatlyClient(\n            \"test_\" + \"x\" * 20, transport=httpx.MockTransport(respond)\n        ) as api:\n            vatly = Vatly(Wiring(api, \"https:\u002F\u002Fapp.example.com\u002Fok\", \"https:\u002F\u002Fapp.example.com\u002Fno\"))\n            return await vatly.customer(\"customer_example\").email()\n\n    assert async_to_sync(read_customer)() == \"buyer@example.com\"\n","python","",[476,493,494,507,528,541,560,567,572,586,605,638,655,665,674,698,719,734,755,776,791,812,827,842,864,885,891,897,903,909,914,928,942,993,1008,1049,1081,1086],{"__ignoreMap":491},[495,496,499,503],"span",{"class":497,"line":498},"line",1,[495,500,502],{"class":501},"s7zQu","import",[495,504,506],{"class":505},"sTEyZ"," httpx\n",[495,508,510,513,516,520,523,525],{"class":497,"line":509},2,[495,511,512],{"class":501},"from",[495,514,515],{"class":505}," asgiref",[495,517,519],{"class":518},"sMK4o",".",[495,521,522],{"class":505},"sync ",[495,524,502],{"class":501},[495,526,527],{"class":505}," async_to_sync\n",[495,529,531,533,536,538],{"class":497,"line":530},3,[495,532,512],{"class":501},[495,534,535],{"class":505}," vatly ",[495,537,502],{"class":501},[495,539,540],{"class":505}," AsyncVatlyClient\n",[495,542,544,546,549,551,554,557],{"class":497,"line":543},4,[495,545,512],{"class":501},[495,547,548],{"class":505}," vatly_fluent ",[495,550,502],{"class":501},[495,552,553],{"class":505}," Vatly",[495,555,556],{"class":518},",",[495,558,559],{"class":505}," Wiring\n",[495,561,563],{"class":497,"line":562},5,[495,564,566],{"emptyLinePlaceholder":565},true,"\n",[495,568,570],{"class":497,"line":569},6,[495,571,566],{"emptyLinePlaceholder":565},[495,573,575,579,583],{"class":497,"line":574},7,[495,576,578],{"class":577},"spNyl","def",[495,580,582],{"class":581},"s2Zo4"," example",[495,584,585],{"class":518},"():\n",[495,587,589,592,595,598,602],{"class":497,"line":588},8,[495,590,591],{"class":577},"    def",[495,593,594],{"class":581}," respond",[495,596,597],{"class":518},"(",[495,599,601],{"class":600},"sHdIc","request",[495,603,604],{"class":518},"):\n",[495,606,608,611,614,616,620,622,625,628,631,635],{"class":497,"line":607},9,[495,609,610],{"class":501},"        assert",[495,612,613],{"class":505}," request",[495,615,519],{"class":518},[495,617,619],{"class":618},"swJcz","url",[495,621,519],{"class":518},[495,623,624],{"class":618},"path",[495,626,627],{"class":518}," ==",[495,629,630],{"class":518}," \"",[495,632,634],{"class":633},"sfazB","\u002Fv1\u002Fcustomers\u002Fcustomer_example",[495,636,637],{"class":518},"\"\n",[495,639,641,644,647,649,652],{"class":497,"line":640},10,[495,642,643],{"class":501},"        return",[495,645,646],{"class":505}," httpx",[495,648,519],{"class":518},[495,650,651],{"class":581},"Response",[495,653,654],{"class":518},"(\n",[495,656,658,662],{"class":497,"line":657},11,[495,659,661],{"class":660},"sbssI","            200",[495,663,664],{"class":518},",\n",[495,666,668,671],{"class":497,"line":667},12,[495,669,670],{"class":600},"            json",[495,672,673],{"class":518},"={\n",[495,675,677,680,683,686,689,691,694,696],{"class":497,"line":676},13,[495,678,679],{"class":518},"                \"",[495,681,682],{"class":633},"id",[495,684,685],{"class":518},"\"",[495,687,688],{"class":518},":",[495,690,630],{"class":518},[495,692,693],{"class":633},"customer_example",[495,695,685],{"class":518},[495,697,664],{"class":518},[495,699,701,703,706,708,710,712,715,717],{"class":497,"line":700},14,[495,702,679],{"class":518},[495,704,705],{"class":633},"resource",[495,707,685],{"class":518},[495,709,688],{"class":518},[495,711,630],{"class":518},[495,713,714],{"class":633},"customer",[495,716,685],{"class":518},[495,718,664],{"class":518},[495,720,722,724,727,729,731],{"class":497,"line":721},15,[495,723,679],{"class":518},[495,725,726],{"class":633},"testmode",[495,728,685],{"class":518},[495,730,688],{"class":518},[495,732,733],{"class":518}," True,\n",[495,735,737,739,742,744,746,748,751,753],{"class":497,"line":736},16,[495,738,679],{"class":518},[495,740,741],{"class":633},"email",[495,743,685],{"class":518},[495,745,688],{"class":518},[495,747,630],{"class":518},[495,749,750],{"class":633},"buyer@example.com",[495,752,685],{"class":518},[495,754,664],{"class":518},[495,756,758,760,763,765,767,769,772,774],{"class":497,"line":757},17,[495,759,679],{"class":518},[495,761,762],{"class":633},"name",[495,764,685],{"class":518},[495,766,688],{"class":518},[495,768,630],{"class":518},[495,770,771],{"class":633},"Alex",[495,773,685],{"class":518},[495,775,664],{"class":518},[495,777,779,781,784,786,788],{"class":497,"line":778},18,[495,780,679],{"class":518},[495,782,783],{"class":633},"metadata",[495,785,685],{"class":518},[495,787,688],{"class":518},[495,789,790],{"class":518}," {},\n",[495,792,794,796,799,801,803,805,808,810],{"class":497,"line":793},19,[495,795,679],{"class":518},[495,797,798],{"class":633},"createdAt",[495,800,685],{"class":518},[495,802,688],{"class":518},[495,804,630],{"class":518},[495,806,807],{"class":633},"2026-01-01T00:00:00Z",[495,809,685],{"class":518},[495,811,664],{"class":518},[495,813,815,817,820,822,824],{"class":497,"line":814},20,[495,816,679],{"class":518},[495,818,819],{"class":633},"links",[495,821,685],{"class":518},[495,823,688],{"class":518},[495,825,826],{"class":518}," {\n",[495,828,830,833,836,838,840],{"class":497,"line":829},21,[495,831,832],{"class":518},"                    \"",[495,834,835],{"class":633},"self",[495,837,685],{"class":518},[495,839,688],{"class":518},[495,841,826],{"class":518},[495,843,845,848,851,853,855,857,860,862],{"class":497,"line":844},22,[495,846,847],{"class":518},"                        \"",[495,849,850],{"class":633},"href",[495,852,685],{"class":518},[495,854,688],{"class":518},[495,856,630],{"class":518},[495,858,859],{"class":633},"https:\u002F\u002Fapi.vatly.com\u002Fv1\u002Fcustomers\u002Fcustomer_example",[495,861,685],{"class":518},[495,863,664],{"class":518},[495,865,867,869,872,874,876,878,881,883],{"class":497,"line":866},23,[495,868,847],{"class":518},[495,870,871],{"class":633},"type",[495,873,685],{"class":518},[495,875,688],{"class":518},[495,877,630],{"class":518},[495,879,880],{"class":633},"application\u002Fjson",[495,882,685],{"class":518},[495,884,664],{"class":518},[495,886,888],{"class":497,"line":887},24,[495,889,890],{"class":518},"                    }\n",[495,892,894],{"class":497,"line":893},25,[495,895,896],{"class":518},"                },\n",[495,898,900],{"class":497,"line":899},26,[495,901,902],{"class":518},"            },\n",[495,904,906],{"class":497,"line":905},27,[495,907,908],{"class":518},"        )\n",[495,910,912],{"class":497,"line":911},28,[495,913,566],{"emptyLinePlaceholder":565},[495,915,917,920,923,926],{"class":497,"line":916},29,[495,918,919],{"class":577},"    async",[495,921,922],{"class":577}," def",[495,924,925],{"class":581}," read_customer",[495,927,585],{"class":518},[495,929,931,934,937,940],{"class":497,"line":930},30,[495,932,933],{"class":501},"        async",[495,935,936],{"class":501}," with",[495,938,939],{"class":581}," AsyncVatlyClient",[495,941,654],{"class":518},[495,943,945,948,951,953,956,958,961,963,966,969,971,974,977,980,982,985,987,990],{"class":497,"line":944},31,[495,946,947],{"class":518},"            \"",[495,949,950],{"class":633},"test_",[495,952,685],{"class":518},[495,954,955],{"class":518}," +",[495,957,630],{"class":518},[495,959,960],{"class":633},"x",[495,962,685],{"class":518},[495,964,965],{"class":518}," *",[495,967,968],{"class":660}," 20",[495,970,556],{"class":518},[495,972,973],{"class":600}," transport",[495,975,976],{"class":518},"=",[495,978,979],{"class":581},"httpx",[495,981,519],{"class":518},[495,983,984],{"class":581},"MockTransport",[495,986,597],{"class":518},[495,988,989],{"class":581},"respond",[495,991,992],{"class":518},")\n",[495,994,996,999,1002,1005],{"class":497,"line":995},32,[495,997,998],{"class":518},"        )",[495,1000,1001],{"class":501}," as",[495,1003,1004],{"class":505}," api",[495,1006,1007],{"class":518},":\n",[495,1009,1011,1014,1016,1018,1020,1023,1025,1028,1030,1032,1035,1037,1039,1041,1044,1046],{"class":497,"line":1010},33,[495,1012,1013],{"class":505},"            vatly ",[495,1015,976],{"class":518},[495,1017,553],{"class":581},[495,1019,597],{"class":518},[495,1021,1022],{"class":581},"Wiring",[495,1024,597],{"class":518},[495,1026,1027],{"class":581},"api",[495,1029,556],{"class":518},[495,1031,630],{"class":518},[495,1033,1034],{"class":633},"https:\u002F\u002Fapp.example.com\u002Fok",[495,1036,685],{"class":518},[495,1038,556],{"class":518},[495,1040,630],{"class":518},[495,1042,1043],{"class":633},"https:\u002F\u002Fapp.example.com\u002Fno",[495,1045,685],{"class":518},[495,1047,1048],{"class":518},"))\n",[495,1050,1052,1055,1058,1061,1063,1065,1067,1069,1071,1073,1076,1078],{"class":497,"line":1051},34,[495,1053,1054],{"class":501},"            return",[495,1056,1057],{"class":501}," await",[495,1059,1060],{"class":505}," vatly",[495,1062,519],{"class":518},[495,1064,714],{"class":581},[495,1066,597],{"class":518},[495,1068,685],{"class":518},[495,1070,693],{"class":633},[495,1072,685],{"class":518},[495,1074,1075],{"class":518},").",[495,1077,741],{"class":581},[495,1079,1080],{"class":518},"()\n",[495,1082,1084],{"class":497,"line":1083},35,[495,1085,566],{"emptyLinePlaceholder":565},[495,1087,1089,1092,1095,1097,1100,1103,1105,1107,1109],{"class":497,"line":1088},36,[495,1090,1091],{"class":501},"    assert",[495,1093,1094],{"class":581}," async_to_sync",[495,1096,597],{"class":518},[495,1098,1099],{"class":581},"read_customer",[495,1101,1102],{"class":518},")()",[495,1104,627],{"class":518},[495,1106,630],{"class":518},[495,1108,750],{"class":633},[495,1110,637],{"class":518},[472,1112,1113],{},"This tests the async stack from synchronous Django code. To test your own checkout\nview, inject a MockTransport-backed AsyncVatlyClient into your billing test and\nassert its request products, idempotency key, redirect and local Checkout record.",[481,1115,1117],{"id":1116},"send-the-same-signed-event-twice","Send the same signed event twice",[486,1119,1121],{"className":488,"code":1120,"language":490,"meta":491,"style":491},"import hashlib\nimport hmac\nimport json\nimport time\nfrom django.test import Client\nfrom django.test.utils import override_settings\n\n\ndef example():\n    stamp = int(time.time())\n    secret = \"offline-test-secret\"\n    raw = json.dumps(\n        {\n            \"id\": \"event_docs\",\n            \"resource\": \"webhook_event\",\n            \"eventName\": \"future.event\",\n            \"reason\": None,\n            \"entityType\": \"future\",\n            \"entityId\": \"future_1\",\n            \"object\": {\"id\": \"future_1\"},\n            \"createdAt\": \"2026-01-01T00:00:00Z\",\n            \"testmode\": True,\n        }\n    ).encode()\n    digest = hmac.new(secret.encode(), str(stamp).encode() + b\".\" + raw, hashlib.sha256).hexdigest()\n    signature = f\"t={stamp},v1={digest}\"\n    client = Client()\n    with override_settings(VATLY_WEBHOOK_SECRET=secret):\n        first = client.post(\n            \"\u002Fbilling\u002Fwebhook\u002F\",\n            raw,\n            content_type=\"application\u002Fjson\",\n            HTTP_VATLY_SIGNATURE=signature,\n        )\n        second = client.post(\n            \"\u002Fbilling\u002Fwebhook\u002F\",\n            raw,\n            content_type=\"application\u002Fjson\",\n            HTTP_VATLY_SIGNATURE=signature,\n        )\n    assert first.content == b\"processed\"\n    assert second.content == b\"duplicate\"\n",[476,1122,1123,1130,1137,1144,1151,1168,1189,1193,1197,1205,1228,1242,1259,1264,1283,1302,1322,1336,1356,1376,1407,1425,1437,1442,1452,1527,1560,1572,1591,1608,1619,1626,1641,1653,1657,1672,1682,1689,1704,1715,1720,1744],{"__ignoreMap":491},[495,1124,1125,1127],{"class":497,"line":498},[495,1126,502],{"class":501},[495,1128,1129],{"class":505}," hashlib\n",[495,1131,1132,1134],{"class":497,"line":509},[495,1133,502],{"class":501},[495,1135,1136],{"class":505}," hmac\n",[495,1138,1139,1141],{"class":497,"line":530},[495,1140,502],{"class":501},[495,1142,1143],{"class":505}," json\n",[495,1145,1146,1148],{"class":497,"line":543},[495,1147,502],{"class":501},[495,1149,1150],{"class":505}," time\n",[495,1152,1153,1155,1158,1160,1163,1165],{"class":497,"line":562},[495,1154,512],{"class":501},[495,1156,1157],{"class":505}," django",[495,1159,519],{"class":518},[495,1161,1162],{"class":505},"test ",[495,1164,502],{"class":501},[495,1166,1167],{"class":505}," Client\n",[495,1169,1170,1172,1174,1176,1179,1181,1184,1186],{"class":497,"line":569},[495,1171,512],{"class":501},[495,1173,1157],{"class":505},[495,1175,519],{"class":518},[495,1177,1178],{"class":505},"test",[495,1180,519],{"class":518},[495,1182,1183],{"class":505},"utils ",[495,1185,502],{"class":501},[495,1187,1188],{"class":505}," override_settings\n",[495,1190,1191],{"class":497,"line":574},[495,1192,566],{"emptyLinePlaceholder":565},[495,1194,1195],{"class":497,"line":588},[495,1196,566],{"emptyLinePlaceholder":565},[495,1198,1199,1201,1203],{"class":497,"line":607},[495,1200,578],{"class":577},[495,1202,582],{"class":581},[495,1204,585],{"class":518},[495,1206,1207,1210,1212,1216,1218,1221,1223,1225],{"class":497,"line":640},[495,1208,1209],{"class":505},"    stamp ",[495,1211,976],{"class":518},[495,1213,1215],{"class":1214},"sBMFI"," int",[495,1217,597],{"class":518},[495,1219,1220],{"class":581},"time",[495,1222,519],{"class":518},[495,1224,1220],{"class":581},[495,1226,1227],{"class":518},"())\n",[495,1229,1230,1233,1235,1237,1240],{"class":497,"line":657},[495,1231,1232],{"class":505},"    secret ",[495,1234,976],{"class":518},[495,1236,630],{"class":518},[495,1238,1239],{"class":633},"offline-test-secret",[495,1241,637],{"class":518},[495,1243,1244,1247,1249,1252,1254,1257],{"class":497,"line":667},[495,1245,1246],{"class":505},"    raw ",[495,1248,976],{"class":518},[495,1250,1251],{"class":505}," json",[495,1253,519],{"class":518},[495,1255,1256],{"class":581},"dumps",[495,1258,654],{"class":518},[495,1260,1261],{"class":497,"line":676},[495,1262,1263],{"class":518},"        {\n",[495,1265,1266,1268,1270,1272,1274,1276,1279,1281],{"class":497,"line":700},[495,1267,947],{"class":518},[495,1269,682],{"class":633},[495,1271,685],{"class":518},[495,1273,688],{"class":518},[495,1275,630],{"class":518},[495,1277,1278],{"class":633},"event_docs",[495,1280,685],{"class":518},[495,1282,664],{"class":518},[495,1284,1285,1287,1289,1291,1293,1295,1298,1300],{"class":497,"line":721},[495,1286,947],{"class":518},[495,1288,705],{"class":633},[495,1290,685],{"class":518},[495,1292,688],{"class":518},[495,1294,630],{"class":518},[495,1296,1297],{"class":633},"webhook_event",[495,1299,685],{"class":518},[495,1301,664],{"class":518},[495,1303,1304,1306,1309,1311,1313,1315,1318,1320],{"class":497,"line":736},[495,1305,947],{"class":518},[495,1307,1308],{"class":633},"eventName",[495,1310,685],{"class":518},[495,1312,688],{"class":518},[495,1314,630],{"class":518},[495,1316,1317],{"class":633},"future.event",[495,1319,685],{"class":518},[495,1321,664],{"class":518},[495,1323,1324,1326,1329,1331,1333],{"class":497,"line":757},[495,1325,947],{"class":518},[495,1327,1328],{"class":633},"reason",[495,1330,685],{"class":518},[495,1332,688],{"class":518},[495,1334,1335],{"class":518}," None,\n",[495,1337,1338,1340,1343,1345,1347,1349,1352,1354],{"class":497,"line":778},[495,1339,947],{"class":518},[495,1341,1342],{"class":633},"entityType",[495,1344,685],{"class":518},[495,1346,688],{"class":518},[495,1348,630],{"class":518},[495,1350,1351],{"class":633},"future",[495,1353,685],{"class":518},[495,1355,664],{"class":518},[495,1357,1358,1360,1363,1365,1367,1369,1372,1374],{"class":497,"line":793},[495,1359,947],{"class":518},[495,1361,1362],{"class":633},"entityId",[495,1364,685],{"class":518},[495,1366,688],{"class":518},[495,1368,630],{"class":518},[495,1370,1371],{"class":633},"future_1",[495,1373,685],{"class":518},[495,1375,664],{"class":518},[495,1377,1378,1380,1383,1385,1387,1390,1392,1394,1396,1398,1400,1402,1404],{"class":497,"line":814},[495,1379,947],{"class":518},[495,1381,1382],{"class":633},"object",[495,1384,685],{"class":518},[495,1386,688],{"class":518},[495,1388,1389],{"class":518}," {",[495,1391,685],{"class":518},[495,1393,682],{"class":633},[495,1395,685],{"class":518},[495,1397,688],{"class":518},[495,1399,630],{"class":518},[495,1401,1371],{"class":633},[495,1403,685],{"class":518},[495,1405,1406],{"class":518},"},\n",[495,1408,1409,1411,1413,1415,1417,1419,1421,1423],{"class":497,"line":829},[495,1410,947],{"class":518},[495,1412,798],{"class":633},[495,1414,685],{"class":518},[495,1416,688],{"class":518},[495,1418,630],{"class":518},[495,1420,807],{"class":633},[495,1422,685],{"class":518},[495,1424,664],{"class":518},[495,1426,1427,1429,1431,1433,1435],{"class":497,"line":844},[495,1428,947],{"class":518},[495,1430,726],{"class":633},[495,1432,685],{"class":518},[495,1434,688],{"class":518},[495,1436,733],{"class":518},[495,1438,1439],{"class":497,"line":866},[495,1440,1441],{"class":518},"        }\n",[495,1443,1444,1447,1450],{"class":497,"line":887},[495,1445,1446],{"class":518},"    ).",[495,1448,1449],{"class":581},"encode",[495,1451,1080],{"class":518},[495,1453,1454,1457,1459,1462,1464,1467,1469,1472,1474,1476,1479,1482,1484,1487,1489,1491,1494,1496,1499,1501,1503,1505,1507,1510,1512,1515,1517,1520,1522,1525],{"class":497,"line":893},[495,1455,1456],{"class":505},"    digest ",[495,1458,976],{"class":518},[495,1460,1461],{"class":505}," hmac",[495,1463,519],{"class":518},[495,1465,1466],{"class":581},"new",[495,1468,597],{"class":518},[495,1470,1471],{"class":581},"secret",[495,1473,519],{"class":518},[495,1475,1449],{"class":581},[495,1477,1478],{"class":518},"(),",[495,1480,1481],{"class":1214}," str",[495,1483,597],{"class":518},[495,1485,1486],{"class":581},"stamp",[495,1488,1075],{"class":518},[495,1490,1449],{"class":581},[495,1492,1493],{"class":518},"()",[495,1495,955],{"class":518},[495,1497,1498],{"class":577}," b",[495,1500,685],{"class":518},[495,1502,519],{"class":633},[495,1504,685],{"class":518},[495,1506,955],{"class":518},[495,1508,1509],{"class":581}," raw",[495,1511,556],{"class":518},[495,1513,1514],{"class":581}," hashlib",[495,1516,519],{"class":518},[495,1518,1519],{"class":618},"sha256",[495,1521,1075],{"class":518},[495,1523,1524],{"class":581},"hexdigest",[495,1526,1080],{"class":518},[495,1528,1529,1532,1534,1537,1540,1543,1545,1548,1551,1553,1556,1558],{"class":497,"line":899},[495,1530,1531],{"class":505},"    signature ",[495,1533,976],{"class":518},[495,1535,1536],{"class":577}," f",[495,1538,1539],{"class":633},"\"t=",[495,1541,1542],{"class":660},"{",[495,1544,1486],{"class":505},[495,1546,1547],{"class":660},"}",[495,1549,1550],{"class":633},",v1=",[495,1552,1542],{"class":660},[495,1554,1555],{"class":505},"digest",[495,1557,1547],{"class":660},[495,1559,637],{"class":633},[495,1561,1562,1565,1567,1570],{"class":497,"line":905},[495,1563,1564],{"class":505},"    client ",[495,1566,976],{"class":518},[495,1568,1569],{"class":581}," Client",[495,1571,1080],{"class":518},[495,1573,1574,1577,1580,1582,1585,1587,1589],{"class":497,"line":911},[495,1575,1576],{"class":501},"    with",[495,1578,1579],{"class":581}," override_settings",[495,1581,597],{"class":518},[495,1583,1584],{"class":600},"VATLY_WEBHOOK_SECRET",[495,1586,976],{"class":518},[495,1588,1471],{"class":581},[495,1590,604],{"class":518},[495,1592,1593,1596,1598,1601,1603,1606],{"class":497,"line":916},[495,1594,1595],{"class":505},"        first ",[495,1597,976],{"class":518},[495,1599,1600],{"class":505}," client",[495,1602,519],{"class":518},[495,1604,1605],{"class":581},"post",[495,1607,654],{"class":518},[495,1609,1610,1612,1615,1617],{"class":497,"line":930},[495,1611,947],{"class":518},[495,1613,1614],{"class":633},"\u002Fbilling\u002Fwebhook\u002F",[495,1616,685],{"class":518},[495,1618,664],{"class":518},[495,1620,1621,1624],{"class":497,"line":944},[495,1622,1623],{"class":581},"            raw",[495,1625,664],{"class":518},[495,1627,1628,1631,1633,1635,1637,1639],{"class":497,"line":995},[495,1629,1630],{"class":600},"            content_type",[495,1632,976],{"class":518},[495,1634,685],{"class":518},[495,1636,880],{"class":633},[495,1638,685],{"class":518},[495,1640,664],{"class":518},[495,1642,1643,1646,1648,1651],{"class":497,"line":1010},[495,1644,1645],{"class":600},"            HTTP_VATLY_SIGNATURE",[495,1647,976],{"class":518},[495,1649,1650],{"class":581},"signature",[495,1652,664],{"class":518},[495,1654,1655],{"class":497,"line":1051},[495,1656,908],{"class":518},[495,1658,1659,1662,1664,1666,1668,1670],{"class":497,"line":1083},[495,1660,1661],{"class":505},"        second ",[495,1663,976],{"class":518},[495,1665,1600],{"class":505},[495,1667,519],{"class":518},[495,1669,1605],{"class":581},[495,1671,654],{"class":518},[495,1673,1674,1676,1678,1680],{"class":497,"line":1088},[495,1675,947],{"class":518},[495,1677,1614],{"class":633},[495,1679,685],{"class":518},[495,1681,664],{"class":518},[495,1683,1685,1687],{"class":497,"line":1684},37,[495,1686,1623],{"class":581},[495,1688,664],{"class":518},[495,1690,1692,1694,1696,1698,1700,1702],{"class":497,"line":1691},38,[495,1693,1630],{"class":600},[495,1695,976],{"class":518},[495,1697,685],{"class":518},[495,1699,880],{"class":633},[495,1701,685],{"class":518},[495,1703,664],{"class":518},[495,1705,1707,1709,1711,1713],{"class":497,"line":1706},39,[495,1708,1645],{"class":600},[495,1710,976],{"class":518},[495,1712,1650],{"class":581},[495,1714,664],{"class":518},[495,1716,1718],{"class":497,"line":1717},40,[495,1719,908],{"class":518},[495,1721,1723,1725,1728,1730,1733,1735,1737,1739,1742],{"class":497,"line":1722},41,[495,1724,1091],{"class":501},[495,1726,1727],{"class":505}," first",[495,1729,519],{"class":518},[495,1731,1732],{"class":618},"content",[495,1734,627],{"class":518},[495,1736,1498],{"class":577},[495,1738,685],{"class":518},[495,1740,1741],{"class":633},"processed",[495,1743,637],{"class":518},[495,1745,1747,1749,1752,1754,1756,1758,1760,1762,1765],{"class":497,"line":1746},42,[495,1748,1091],{"class":501},[495,1750,1751],{"class":505}," second",[495,1753,519],{"class":518},[495,1755,1732],{"class":618},[495,1757,627],{"class":518},[495,1759,1498],{"class":577},[495,1761,685],{"class":518},[495,1763,1764],{"class":633},"duplicate",[495,1766,637],{"class":518},[472,1768,1769,1770,1773],{},"Run with migrations applied in the test database and the billing URL prefix from\n",[1771,1772,417],"a",{"href":418},". Use a test API key and scope in test settings;\nthis signed unknown event requires no remote API reads. Add tests for bad signatures,\nrollback, CSRF, unauthorized billables and concurrent duplicates on PostgreSQL.",[472,1775,1776,1779,1780],{},[1771,1777,1778],{"href":448},"Contributor checks"," · ",[1771,1781,280],{"href":1782,"rel":1783},"https:\u002F\u002Fdocs.vatly.com\u002Fapi-reference",[1784],"nofollow",[1786,1787,1788],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":491,"searchDepth":509,"depth":509,"links":1790},[1791,1792],{"id":483,"depth":509,"text":484},{"id":1116,"depth":509,"text":1117},"Use Django's test database and httpx fixtures.","md",null,{},{"title":58},{"title":467,"description":1793},"cU3oatupSrhiLk99vpxeWhG7HbfoW29TvZQ5y3IDC7w",[1801,1803],{"title":441,"path":442,"stem":443,"description":1802,"children":-1},"When django.contrib.admin and vatly_django are installed, billing models register automatically.",{"title":363,"path":448,"stem":449,"description":1804,"children":-1},"Set up the repository, run checks and build the Django package locally.",1794594934562]