{"id":13821808,"url":"https://github.com/samber/invoice-as-a-service","last_synced_at":"2025-04-12T23:37:47.827Z","repository":{"id":37587833,"uuid":"124877895","full_name":"samber/invoice-as-a-service","owner":"samber","description":"💰 Simple invoicing service (REST API): from JSON to PDF","archived":false,"fork":false,"pushed_at":"2025-01-11T14:55:32.000Z","size":1567,"stargazers_count":208,"open_issues_count":5,"forks_count":43,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-12T23:37:28.202Z","etag":null,"topics":["api","braintree","hosted","invoice","json","laravel","nocode","paymentwall","paypal","pdf","rest","saas","self-hosted","stripe"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/samber.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-12T11:20:16.000Z","updated_at":"2025-02-24T14:57:05.000Z","dependencies_parsed_at":"2024-05-28T22:01:19.511Z","dependency_job_id":"680372a9-49c6-4161-810c-5d499bb546a8","html_url":"https://github.com/samber/invoice-as-a-service","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samber%2Finvoice-as-a-service","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samber%2Finvoice-as-a-service/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samber%2Finvoice-as-a-service/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samber%2Finvoice-as-a-service/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/samber","download_url":"https://codeload.github.com/samber/invoice-as-a-service/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248647255,"owners_count":21139081,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","braintree","hosted","invoice","json","laravel","nocode","paymentwall","paypal","pdf","rest","saas","self-hosted","stripe"],"created_at":"2024-08-04T08:01:29.122Z","updated_at":"2025-04-12T23:37:47.798Z","avatar_url":"https://github.com/samber.png","language":"PHP","funding_links":[],"categories":["PHP"],"sub_categories":[],"readme":"\n# Invoice as a service\n\nThis service **generates professional looking PDF invoices**, from a simple POST HTTP request with json payload.\n\n## File destinations / storage\n\nRendered file can be returned into the HTTP response or exported to:\n\n- AWS S3 (and any compatible storage destination)\n- FTP server\n- Webhook\n- **Zapier**: \"Catch hook\" trigger, can be linked to Drive, Dropbox...\n\n## Demo\n\n\u003ckbd\u003e\n    \u003cimg alt=\"Screenshot\" src=\"/example.png\"\u003e\n\u003c/kbd\u003e\n\n## Usage\n\nI provide `invoice-as-a-service` with a full hosted environment for fast and easy setup (endpoint: https://invoice-as-a-service.cleverapps.io).\n\nFor improved privacy, you can also deploy the project on your own infrastructure for free.\n\n### Hosted\n\n```sh\n$ curl \"https://invoice-as-a-service.cleverapps.io/api/invoice/generate\" \\\n     -X POST -H \"content-type: application/json\" \\\n     -d '{\n\n        \"id\": \"42\",\n        \"currency\": \"€\",\n        \"lang\": \"en\",\n        \"date\": 1520852472,\n        \"due_date\": 1521457272,\n        \"paid\": false,\n        \"payment_link\": \"https://screeb.app/user/invoices/42/pay\",\n        \"decimals\": 2,\n        \"notes\": \"Lorem ipsum dolor sit amet.\",\n\n        \"items\": [\n            {\n                \"title\": \"'Growth' plan Screeb.app\",\n                \"description\": \"1 year subscription\",\n                \"price\": 42,\n                \"quantity\": 1,\n                \"tax\": 20\n            }\n        ],\n\n        \"customer\": {\n            \"summary\": \"John Doe\",\n            \"address_line_1\": \"Baxter Building, 42nd street, Madison Avenue\",\n            \"address_line_2\": \"Manhattan, NY, 11234\",\n            \"address_line_3\": \"United States\",\n            \"address_line_4\": \"Earth\",\n            \"phone\": \"1-888-548-0034\",\n            \"email\": \"john@gmail.com\"\n        },\n\n        \"company\": {\n            \"summary\": \"Screeb\",\n            \"address_line_1\": \"123, place de Bretagne\",\n            \"address_line_2\": \"44000 Nantes\",\n            \"address_line_3\": \"France\",\n            \"address_line_4\": \"Earth\",\n            \"phone\": \"1-888-548-0034\",\n            \"email\": \"billing@screeb.app\",\n            \"logo_url\": \"https://raw.githubusercontent.com/samber/invoice-as-a-service/master/screeb-logo.png\",\n            \"other\": [\n                \"EMEA office\",\n                {\n                    \"title\": \"Business hours\",\n                    \"content\": \"9am - 6pm\"\n                }\n            ]\n        },\n\n        \"s3\": {\n            \"presigned_url\": null\n        },\n\n        \"ftp\": {\n        \t\"host\": \"127.0.0.1\",\n        \t\"username\": \"ftpuser\",\n        \t\"password\": \"superSecretPassword\",\n        \t\"path\" : \"/var/html/share/\"\n        },\n\n        \"webhook\": {\n            \"url\": \"https://webhook.example.com/invoice/store\",\n            \"headers\": {\n                \"x-token\": \"very-secret-token\"\n            }\n        },\n\n        \"zapier\": {\n            \"zap_url\": \"https://hooks.zapier.com/hooks/catch/xxxxxxx/yyyyyy\",\n            \"filename\": \"invoice-42.pdf\"\n        }\n\n     }'\n```\n\n### Self hosted\n\n```sh\n$ composer install\n$ php artisan serve\n```\n\n```sh\n$ curl \"http://localhost:8000/api/invoice/generate\" \\\n     -X POST -H \"content-type: application/json\" \\\n     -d '{ ... }'\n```\n\n### User interface from contributor\n\nHere =\u003e [crocomo2744.github.io/Invoicing-form](https://crocomo2744.github.io/Invoicing-form/)\n\n## Properties\n\n| Property | Type | Required | Description | Example |\n| --- | --- | :---: | --- | --- |\n| **id** | string | yes | Your invoice reference | \"42\" |\n| **currency** | string | yes | Your billing currency | \"€\" |\n| **lang** | string | yes | Only english supported for now | \"en\" |\n| **tax** | float | yes | Tax percentage | 20 |\n| **date** | integer | yes | Timestamp of invoice creation date | 1520852472 |\n| **due_date** | integer | yes | Timestamp of invoice due date | 1521457272 |\n| **paid** | boolean | no | Adding a \"paid\" image (default: false) | false |\n| **payment_link** | string | no | Payment link | \"https://\u003cspan\u003e\u003c/span\u003escreeb.app/user/invoices/42/pay\" |\n| **decimals** | integer | no | Number decimals for prices (default: 2) | 2 |\n| **notes** | string | no | Terms, conditions or anything you have to write in order to edit a valid invoice. | \"Lorem ipsum dolor sit amet.\" |\n| **items** | array | yes | List of items | [ Item(...), Item(...) ] |\n| **customer** | object | yes | Customer infos | Customer(...) |\n| **company** | object | yes | Company infos | Company(...) |\n| **s3** | object | false | AWS S3 invoice upload | S3Upload(...) |\n| **ftp** | object | false | FTP invoice upload | FTPUpload(...) |\n| **webhook** | object | false | Webhook invoice upload | WebhookUpload(...) |\n| **zapier** | object | false | Zapier invoice upload | ZapierUpload(...) |\n\n### Item:\n\n| Property | Type | Required | Description | Example |\n| --- | --- | :---: | --- | --- |\n| **title** | string | yes | Product or service name | \"'Growth' plan Screeb.app\" |\n| **description** | string | no | Product or service description | \"1 year subscription\" |\n| **price** | float | yes | Product or service price | 42 |\n| **quantity** | float | no | Product or service quantity (default: 1) | 1 |\n| **tax** | float | no | Tax rate (default: 0) | 1 |\n\n### Customer:\n\n| Property | Type | Required | Description | Example |\n| --- | --- | :---: | --- | --- |\n| **summary** | string | yes | Organisation or customer name | \"John Doe\" |\n| **address_line_1** | string | yes | Customer address, line 1 | \"Baxter Building, 42nd street, Madison Avenue\" |\n| **address_line_2** | string | no | Customer address, line 2 | \"Manhattan, NY, 11234\" |\n| **address_line_3** | string | no | Customer address, line 3 | \"United States\" |\n| **address_line_4** | string | no | Customer address, line 4 | \"Earth\" |\n| **phone** | string | no | Customer phone number | \"1-888-548-0034\" |\n| **email** | string | no | Customer email address | \"john@gmail.com\" |\n| **siret** (deprecated) | string | no | French company identification number | \"539 138 107 00021\" |\n| **other** | array of mixed string and Other() | no | Customer additional infos | [ String, Other(), ... ] |\n\n### Company:\n\n| Property | Type | Required | Description | Example |\n| --- | --- | :---: | --- | --- |\n| **summary** | string | yes | Your organisation name | \"Screeb\" |\n| **address_line_1** | string | yes | Customer address, line 1 | \"123, place de Bretagne\" |\n| **address_line_2** | string | no | Customer address, line 2 | \"44000 Nantes\" |\n| **address_line_3** | string | no | Customer address, line 3 | \"France\" |\n| **address_line_4** | string | no | Customer address, line 4 | \"Earth\" |\n| **phone** | string | no | Customer phone number | \"1-888-548-0034\" |\n| **email** | string | no | Customer email address | \"billing@screeb.app\" |\n| **logo_url** | string | no | URL of your company logo | \"https://\u003cspan\u003e\u003c/span\u003eacme.corp/logo.png\" |\n| **logo_b64** | string | no | Base64 encoded image of your company logo | \"data:image/png;base64,.........\" |\n| **siret** (deprecated) | string | no | French company identification number | \"539 138 107 00021\" |\n| **other** | array of mixed string and Other() | no | Company additional infos | [ String, Other(), ... ] |\n\n### customer.other[].* and company.other[].*\n\n`customer.other` and `company.other` fields are arrays of mixed type: simple string or the following object:\n\n| Property | Type | Required | Description | Example |\n| --- | --- | :---: | --- | --- |\n| **title** | string | true | Field name | \"Twitter handle\" |\n| **content** | string | true | Field value | \"@foobar\" |\n\n### S3 upload\n\n| Property | Type | Required | Description | Example |\n| --- | --- | :---: | --- | --- |\n| **presigned_url** | string | false | Presigned AWS S3 upload url | \"https://\u003cspan\u003e\u003c/span\u003emy-bucket.s3.eu-central-1.amazonaws.com/201807250018--foobar@example.com.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=xxxx\u0026X-Amz-Date=xxxx\u0026X-Amz-Expires=xxxx\u0026X-Amz-Signature=xxxx\u0026X-Amz-SignedHeaders=host\" |\n\n### FTP upload\n\n| Property | Type | Required | Description | Example |\n| --- | --- | :---: | --- | --- |\n| **host** | string | true | The host, IP Address of the server | \"ftp.example.com\" |\n| **username** | string | true | The ftp username to connect | \"john\" |\n| **password** | string | true | The ftp password of the user you are trying to connect | \"test1234\" |\n| **port** | integer | false | The port used to connect, default is 21. | 21 |\n| **ssl** | boolean | false | If the connection supports SSL mention that here, default is false. | true |\n| **passive** | boolean | false | If it should use a passive connection, default is true. | true |\n| **path** | string | true | The full path on the server where you want the invoice to be uploaded. | \"/home/john/share\" |\n\n### Webhook upload\n\n| Property | Type | Required | Description | Example |\n| --- | --- | :---: | --- | --- |\n| **url** | string | true | The URL of the destination webhook | \"https://webhook.example.com/invoice/store\" |\n| **headers** | object | false | These headers will be inserted into webhook request | { \"x-token\": \"very-secret-token\" } |\n\n### Zapier upload\n\n| Property | Type | Required | Description | Example |\n| --- | --- | :---: | --- | --- |\n| **zap_url** | string | true | URL of Zapier Hook | \"https://hooks.zapier.com/hooks/catch/xxxxxxx/yyyyyy\" |\n| **filename** | string | false | Filename that will be provided into Zapier Hook | \"invoice-42.pdf\" |\n\n## Notes\n\nThe provided logo_url (optional) must be accessible from the `invoice-as-a-service` API !\n\n## Contribute\n\nHell yeah!\n\nClone + pull-request.\n\nI usually reply in hours or days ;)\n\nMagic happens here:\n- template: `resources/views/invoices/default.blade.php`\n- controller + input validation: `app/Http/Controllers/InvoiceController.php`\n- pdf build: `app/Helpers/PDF.php`\n- invoice storage: `app/Helpers/Storage.php`\n\n### AWS S3 - Generate presigned upload url:\n\n```sh\n$ aws configure\n$ node ./scripts/presign-upload-url.js \u003cregion\u003e \u003cmy-bucket\u003e invoices/201807250018--foobar@example.com.pdf\n```\n\n### Update dependencies\n\n```bash\n$ composer outdated -D\n$ composer update \u003cpackage-name\u003e --with-dependencies\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamber%2Finvoice-as-a-service","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamber%2Finvoice-as-a-service","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamber%2Finvoice-as-a-service/lists"}